Etiqueta: docker

  • XDebug con VSCode y Docker en Ubuntu

    Usar Docker en proyectos PHP es un viaje de ida.

    Olvidarse del «te juro que en mi casa andaba!» es una bendición.

    Claro que, para poder desplegar, primero hay que desarrollar. Y desarrollar implica, claro está, debuggear.

    En PHP no contamos con un debugger incorporado a nuestros IDEs… afortunadamente existe XDebug.

    El problema, sin embargo, suele ser la configuración que depende de dos factores que deben combinarse:

    1. La instalación y configuración del lado del servidor.
    2. La configuración del IDE para poder utilizarlo.

    Existen muchas combinaciones posibles para realizar esta tarea, cada una con sus pequeñas particularidades. En este artículo me enfocaré en una de las combinaciones más populares por estos días:

    VSCode sobre Ubuntu con un WebServer montado en Docker.

    La aplicación que usaré como ejemplo es el CRM de código abierto rukovoditel.

    El Dockerfile

    Lo primero será definir el archivo Dockerfile que permita contar con un servidor web que pueda ejecutar php y, a la vez, tenga instalado XDebug:

    FROM php:7.4-apache
    LABEL authors="mauro.chojrin@leewayweb.com"
    
    RUN apt-get update && \
        apt-get install -y \
            libpng-dev \
            libzip-dev && \
            pecl install xdebug-3.1.6
    
    RUN docker-php-ext-install gd && \
        docker-php-ext-install zip && \
        docker-php-ext-install mysqli && \
        docker-php-ext-enable xdebug
    
    COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
    
    ADD app /var/www/html
    
    RUN chown -R www-data.www-data /var/www/html

    La configuración de XDebug

    A continuación ha de crearse el archivo de configuración de xdebug (xdebug.ini) en la raíz del proyecto:

    zend_extension=xdebug
    
    [xdebug]
    xdebug.mode=develop,debug
    xdebug.client_host=host.docker.internal
    xdebug.start_with_request=yes

    El archivo docker-compose.yml

    Posteriormente será el turno del archivo docker-compose.yml que contendrá los servicios necesarios para dar vida a la aplicación:

    version: '3.1'
    services:
      mysql:
        image: 'mysql:5.7.42-debian'
        environment:
          - MYSQL_ROOT_PASSWORD=root
          - MYSQL_DATABASE=ruko
          - MYSQL_USER=ruko
          - MYSQL_PASSWORD=ruko
        restart: always
      webserver:
        image: 'ruko_ws'
        build:
          context: '.'
        ports:
          - '8888:80'
        volumes:
          - './app:/var/www/html:rw'
          - './xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini'
        extra_hosts:
          - host.docker.internal:host-gateway

    Con esto está listo todo lo necesario del lado de la infraestructura.

    Los siguientes pasos se darán del lado del host.

    Configuración de VS Code

    La extensión de debugging de PHP

    Una vez abierto el proyecto, hay que asegurarse de tener instalada la extensión requerida para realizar debugging:

    La configuración de lanzamiento

    A continuación, debe crearse una configuración de lanzamiento para realizar el debugging:

    De las múltiples entradas que encuentro la que interesa es la llamada Listen for Xdebug.

    Por defecto, lo que se ve es:

    {
          "name": "Listen for Xdebug",
          "type": "php",
          "request": "launch",
          "port": 9003
    },

    Lo que se necesita es agregar la definición del mapeo de directorios, desde el local al del servidor.

    En este caso, el directorio en el servidor (en el contenedor Docker) es /var/www/html/, el cual debe ser conectado con el directorio app dentro de la raíz del proyecto.

    Para usar el directorio del host, sin hardcodearlo, es posible usar la variable de VisualStudio workspaceFolder la cual contiene el directorio raíz del proyecto.

    De modo que la configuración quedará de esta forma:

    {
          "name": "Listen for Xdebug",
          "type": "php",
          "request": "launch",
          "port": 9003,
          "pathMappings": {
                 "/var/www/html/": "${workspaceFolder}/app"
          }
    },

    Debuggeando

    Con esto listo es posible arrancar el debugger:

    Para ver su efecto es conveniente introducir un punto de interrupción (breakpoint) en algún lugar del código.

    Tomemos como ejemplo el archivo app/install/index.php ya que es el primero que se ejecuta al ingresar a la aplicación.

    Lo próximo será ir al navegador web, donde se dará comienzo a la sesión de debugging usando el asistente de XDebug.

    Luego se debe ingresar la dirección de la página (http://localhost:8888 en este caso) y, al dar enter se abrirá automáticamente la ventana de VS Code:

    Donde podrá ejecutarse el código paso a paso:

    Inspeccionar variables en tiempo real

    Y, en general, utilizar todos los servicios provistos por XDebug.

    Puntos clave

    En resúmen, las claves para hacer funcionar XDebug con VSCode en Docker sobre Ubuntu son:

    1. Contar con una imagen basada en un Dockerfile que incluya la instalación de XDebug
    2. Tener instalada la extensión de debugging con PHP en VS Code
    3. Configurar correctamente el mapeo de directorios en la configuración de lanzamiento (launch.json)
    4. Tener la definición de extra_hosts del contenedor que tiene php apuntando a host-gateway
    5. Tener el xdebug correctamente configurado dentro del contenedor de php
  • ¿Cualquier aplicación PHP se puede dockerizar?

    ¿Cualquier aplicación PHP se puede dockerizar?

    ¿Vale la pena Dockerizar tu php?

    Permitime contestarte con un ejercicio.

    Imaginate esta situación:

    Venís trabajando sin descanso en una aplicación muy importante para entregar a un cliente.

    Vas a buen ritmo, vas a llegar a la entrega sin mucho problema.

    De pronto, te aparece la notificación de actualizar el sistema operativo y pensás: «Y… la verdad que no estaría mal… no puedo seguir toda la vida con la 1.0…».

    Le das aceptar y, luego de unos minutos, cuando todo terminó te das cuenta de que la aplicación que andaba perfecta dejó de funcionar.

    ¿Eh?

    ¿Cómo puede ser?

    Así como instintivamente tirás un php -v y comprobás que de 7.4 saltaste sin escalas a 8.1… y las cosas ya no son como antes.

    ¡Qué problema! Menos mal que es una situación hipotética ¿no?

    Pues… no tanto. Esta historia es una adaptación libre de esta conversación que leí recientemente:

    «se me actualizo php a la version 8 en Manjaro, y por ende se me descuadró todo, qué tengo que cambiar en el httpd.conf para que me funcione php8«

    «Soy usuario de manjaro y me pasó lo mismo. Pero por suerte tenia dockerizado mis proyectos y no sufrí demasiado, deberías considerarlo«

    Yo diría que suerte habría sido no tener que enfrentarse al problema.

    Tener tus proyectos php dockerizados no es suerte, es una decisión.

    Una decisión que en algún momento este desarrollador tomó y que también deberías, al menos, evaluar.

    Es un caso muy similar al que analizo acá.

    Pensando un poco en esto empecé a preguntarme: ¿Cualquier aplicación php se puede dockerizar?

    Qué significa dockerizar una aplicación PHP

    Cuando se habla de dockerizar (me encanta este verbo) una aplicación, se hace referencia a hacer las adaptaciones necesarias para poder correrla sobre contenedores docker, tanto en un etorno de desarrollo como en uno de producción.

    Estos ajustes dependen en gran medida de la naturaleza de la aplicación pero, a rasgos generales, se trata de:

    • Crear un Dockerfile (O al menos seleccionar una imagen pre-existente que sea compatible con las necesidades de la aplicación)
    • Cambiar, si las hubiera, referencias a localhost por otras que apunten a servicios dentro del ecosistema de docker
    • Crear una configuración de inicio de los servicios (Ya sea a través de Makefiles o similar o, mejor aún, a través de un archivo docker-compose)

    En principio creo que no hay mucho más, pero si te parece que me olvidé de algo importante, por favor dejame un comentario abajo.

    Qué se necesita para dockerizar una aplicación PHP

    Para dockerizar una aplicación PHP se necesita, primero que nada, contar, tanto en local como en producción, con el motor y el cliente de docker.

    Si se pretende usar docker-compose, también deberá estar presente en ambos lados.

    Más allá de eso, es conveniente contar con un buen IDE, aunque no es imprescindible.

    Técnicamente no se necesita nada más. Claro que saber lo que se está haciendo ayuda mucho.

    Cómo dockerizar una aplicación PHP

    Teniendo todo en su lugar el proceso es simple, aunque, dependiendo de la aplicación, puede ser más laborioso que en otros casos.

    Relevamiento

    Lo primero es entender cuáles son las dependencias:

    • ¿Qué versión de PHP usás en producción?
    • ¿Qué extensiones de PHP necesitás instaladas y habilitadas?
    • ¿Qué otros servicios de infraestructura se usan con tu aplicación? ¿MySQL? ¿Redis?
      • ¿Qué versiones?
    • ¿Cómo está la configuración del webserver?
    • ¿Cómo está la configuración de PHP?
    • ¿Qué permisos sobre archivos necesita la aplicación para funcionar?

    Con las respuestasa a estas preguntas podrás darte una idea de lo que requerirás en tu imagen docker.

    Instalación de las herramientas

    Si no las tienes disponibles, el próximo paso será instalar las herramientas necesarias (docker engine, docker client y docker-compose al menos).

    Adaptación de la aplicación

    Luego deberás preparar la aplicación:

    • Reemplazar referencias a servicios externos (Bases de datos, colas de mensajes, etc…) de IPs o nombres conocidos en el host a nombres conocidos dentro de la red de Docker
    • Reemplazar rutas absolutas por relativas
    • Reemplazar enlaces simbólicos por archivos concretos

    Creación de los archivos de Docker

    Es muy probable que tu aplicación tenga algunos requisitos específicos que no encuentres en una de las imágenes disponibles en el dockerhub. No te preocupes, siempre podés tomar una imagen lo más parecida posible a tus necesidades para usar como base y agregar tus cambios particulares.

    Si el sistema es suficientemente complejo (si requiere de otros componentes de infraestructura), es conveniente definir también un archivo docker-compose.yml para mayor comodidad.

    Pruebas y ajustes

    Una vez hayas pasado por los pasos anteriores será cuestión de probar la aplicación y validar que todo funciona.

    Los comandos exactos dependerán de cómo hayas armado los archivos de configuración, pero será algo así como:

    docker build . -t mi_php
    
    docker run -it mi_php 

    O, si usas docker-compose:

    docker-compose up --build

    Una vez estén levantados los servicios podrás entrar a http://localhost:8000 (Asumo que el puerto 8000 está mapeado al 80 en el contenedor) y ya podrás verificar que toda la aplicación funciona.

    Por qué dockerizar tus aplicaciones php

    Si te parece mucho trabajo, tenés razón, dockerizar una aplicación PHP puede ser molesto, especialmente cuando lo tienes que hacer por primera vez pero, si queda bien, es muy probable que no tengas que volver a hacerlo por mucho tiempo y, a la vez, tu aplicación quedará blindada ante cambios en el ambiente, tanto local como de producción.

    De pronto no se ve tan mal, ¿no?

  • Por qué NO deberías usar XAMPP

    Por qué NO deberías usar XAMPP

    Me llegó esta pregunta que me pareció interesante compartir:

    Estoy usando PHPStorm, y como sólo me pide el intérprete cuando trato de ejecutar en el navegador, todavía no lo he instaldo, quisiera saber si ya es mejor instalar el Xampp, si es recomendable y en caso de que no lo sea ¿por que?

    Por si no sabés de qué se trata XAMPP, es un paquete que trae, todo lo que típicamente se requiere para desarrollar con PHP:

    La X del comienzo puede ser reemplazada por L (Linux), W (Windows) o M (Mac).

    A primera vista parece la panacea, ¿no?

    «Es lo más fácil!»

    «Un par de clics y listo!»

    «¿Para qué complicarme instalando todo por separado si puedo tenerlo en un solo paquete»?

    Seguramente habrás escuchado este tipo de argumentos a su favor.

    Y sí, todo eso es verdad: XAMPP es un paquete sumamente cómodo… al principio.

    Los problemas llegan cuando:

    • Es momento de ir a producción
    • Necesitás trabajar con diferentes proyectos a la vez.

    Son estos los momentos en te das cuenta que el salvavidas estaba hecho de plomo.

    Cuál es el problema con XAMPP

    La sencillez que aporta XAMPP lo hace la opción más difundida entre los desarrolladores menos experimentados. Pero esa sencillez tiene un costo.

    El primero de los problemas es que, al ocultar la complejidad real que implica montar un servidor, se propicia el efecto «¡Te juro que en mi casa andaba!». Como no sabés realmente qué tenés instalado es difícil verificar que el hosting tenga lo mismo (Más detalle de qué es exactamente lo que deberías mirar acá).

    El segundo de los problemas es que hace muy difícil trabajar en diferentes proyectos donde cada uno tiene requerimientos de infraestructura diferentes (Por ejemplo, versiones diferentes del intérprete de PHP).

    Por supuesto que, si sos conciente de estas limitaciones y sabés trabajar con ellas XAMPP puede ser una opción aceptable.

    Qué usar en lugar de XAMPP

    Las opciones son varias, hay algunas mejores que XAMPP y otras peores:

    En general, docker es la mejor opción cuando se trata de montar entornos locales ya que es muy simple luego llevarlos a producción y/o compartir con tu equipo.

    Pero bueno, es cierto también que dominarlo no es una tarea muy sencilla.

    Si recién estás empezando (Y quiero decir que apenas estás dando tus primeros pasos), está bien que uses XAMPP pero es importante que tengas la idea de migrar lo antes posible.

  • «Mi sitio funcionaba bien hasta que el hosting actualizó PHP»

    «Mi sitio funcionaba bien hasta que el hosting actualizó PHP»

    Hace poco me contactó un colega por una situación algo complicada que le tocó enfrentar.

    La historia comienza así:

    Nuestro sitio está programado con PHP 5.5 y usa memcached. Estamos queriendo migrarlo a una versión más alta de PHP y tenemos un problemita.

    Y sigue:

    …guardamos la sesión en memcache porque tenemos varios fronts y dependiendo de la versión el error es diferente

    Se va poniendo interesante, ¿no? Veamos un poco más:

    …con php 5.5 todo andaba perfecto, tanto en Windows con WAMP para desarrollar como con Linux/Centos

    El resto te lo podrás imaginar supongo.

    En general no soy muy partidario de desarrollar en Windows y desplegar en Linux (Una de las razones que llevan a la falsa idea de que todo va a funcionar bien).

    Vayamos a lo importante: ¿cómo tomaron la decisión de migrar a una versión más actualizada?

    …la gente que instala los servidores sugirió ir a la última versión de PHP y Apache y Centos y postgresql pero no va

    Bien, ahora está más claro.

    Llegados a este punto estamos realmente en un problema: por un lado, el sitio tiene que seguir funcionando.

    Por el otro, no podemos pedirle al hosting que habilite una versión de PHP que sabemos que es compatible con nuestro sistema.

    ¿Qué se puede hacer?

    Lo mejor sería buscar una imagen de docker que tenga la versión que buscamos, instalarla en el servidor y seguir la vida como si tal cosa.

    Si esa no es una posibilidad, habrá que hacerse a la idea de que la solución tomará algún tiempo… con todo lo que ello implica.

    Saltarse versiones de php puede ser bastante arriesgado.

    En este caso, ir de la 5.5 directo a la 8.1 implica dejar de lado una serie de cambios que se realizaron al intérprete a tavés de los años, algunos para hacerlo más eficiente y otros para quitarle funciones que ya pueden seguir soportándose.

    El camino más seguro llegados a este punto sería ir bajando de versión del lado del hosting (8.1., 8.0, 7.4 y así) hasta llegar a una que, o bien sea compatible con el sistema, o sea la más antigua soportada por el proveedor.

    Si se llega al primer escenario (Una versión superior a la que veníamos usando pero en la que el sistema funciona bien) perfecto, tema resuelto.

    Si, en cambio, la versión más antigua con la que podemos contar no es compatible con el sistema, tenemos trabajo por delante.

    Supongamos por tomar un ejemplo que la versión más baja que nos permite usar el proveedor es la 7.1.

    Entre la versión 5.5 y la 7.1 hubo tres versiones intermedias (5.6, 7.0 y la propia 7.1).

    La manera más segura de llegar de una versión de php a otra es pasar por todas las intermedias.

    Antes de que me lo digas, sí, es un trabajo arduo y molesto, lo sé… pero me temo que es la posibilidad menos riesgosa, así que… más vale empezar a trabajar.

    Lo que vas a necesitar es seguir este proceso:

    1. Instalar en un ambiente de pruebas la versión a la que vas a intentar migrar (5.6 sería la primera en este caso)
    2. Instalar y configurar el sistema en dicho ambiente de pruebas
    3. Ejecutar las pruebas
    4. Hacer los ajustes correspondientes al código
    5. Pasar a la siguiente versión y volver al paso 1

    Algunas herramientas que te van a ayudar

    Existen algunas herramientas en las que te podés apoyar para hacer este proceso algo menos laborioso:

    En general, migrar a una nueva versión de php no es precisamente una tarea sencilla pero si encima lo tenés que hacer a las apuradas… puede volverse una verdadera pesadilla.

    Esto es algo que difícilmente puedas prevenir si estás en ambientes de hosting que no controlás.

    Si este es tu caso tal vez te convenga evaluar migrarte hacia tu propio servidor.

  • 3 Herramientas para usar Docker con PHP

    3 Herramientas para usar Docker con PHP

    Escuchaste a más de un colega comentar que Docker es una gran herramienta y te estás empezando a preguntar si no te estás perdiendo de algo.

    Miraste un poco la documentación y, honestamente, el calificativo amigable le queda algo holgado… por decirlo amablemente.

    Todo ese tema de las imágenes, los contenedores, los volúmenes… es mucho.

    Y de entrada toparse con un archivo como:

    FROM php:7.1-apache
    
    LABEL vendor="Mautic"
    LABEL maintainer="Luiz Eduardo Oliveira Fonseca <luiz@powertic.com>"
    
    # Install PHP extensions
    RUN apt-get update && apt-get install --no-install-recommends -y \
        cron \
        git \
        wget \
        sudo \
        libc-client-dev \
        libicu-dev \
        libkrb5-dev \
        libmcrypt-dev \
        libssl-dev \
        libz-dev \
        unzip \
        zip \
        && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
        && rm -rf /var/lib/apt/lists/* \
        && rm /etc/cron.daily/*
    
    RUN docker-php-ext-configure imap --with-imap --with-imap-ssl --with-kerberos \
        && docker-php-ext-configure opcache --enable-opcache \
        && docker-php-ext-install imap intl mbstring mcrypt mysqli pdo_mysql zip opcache bcmath\
        && docker-php-ext-enable imap intl mbstring mcrypt mysqli pdo_mysql zip opcache bcmath
    
    # Install composer
    RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
    
    # Define Mautic volume to persist data
    VOLUME /var/www/html
    
    # Define Mautic version and expected SHA1 signature
    ENV MAUTIC_VERSION 2.16.2
    ENV MAUTIC_SHA1 df6735df8d7d31cc6bc505c38ee8147b40b8311b
    
    # By default enable cron jobs
    ENV MAUTIC_RUN_CRON_JOBS true
    
    # Setting an root user for test
    ENV MAUTIC_DB_USER root
    ENV MAUTIC_DB_NAME mautic
    
    # Setting PHP properties
    ENV PHP_INI_DATE_TIMEZONE='UTC' \
        PHP_MEMORY_LIMIT=512M \
        PHP_MAX_UPLOAD=128M \
        PHP_MAX_EXECUTION_TIME=300
    
    # Download package and extract to web volume
    RUN curl -o mautic.zip -SL https://github.com/mautic/mautic/releases/download/${MAUTIC_VERSION}/${MAUTIC_VERSION}.zip \
        && echo "$MAUTIC_SHA1 *mautic.zip" | sha1sum -c - \
        && mkdir /usr/src/mautic \
        && unzip mautic.zip -d /usr/src/mautic \
        && rm mautic.zip \
        && chown -R www-data:www-data /usr/src/mautic
    
    # Copy init scripts and custom .htaccess
    COPY docker-entrypoint.sh /entrypoint.sh
    COPY makeconfig.php /makeconfig.php
    COPY makedb.php /makedb.php
    COPY mautic.crontab /etc/cron.d/mautic
    RUN chmod 644 /etc/cron.d/mautic
    
    # Enable Apache Rewrite Module
    RUN a2enmod rewrite
    
    # Apply necessary permissions
    RUN ["chmod", "+x", "/entrypoint.sh"]
    ENTRYPOINT ["/entrypoint.sh"]
    
    CMD ["apache2-foreground"]

    No da muchas ganas de incursionar, ¿cierto?

    Todo lo que querías era hacer una prueba sencilla. Como para comprobar por tus propios medios, si todo lo que te dijeron de Docker era realmente así y en cambio… tenés que ponerte a escribir archivos de texto inentendibles.

    Te tengo buenas noticias: hay varias herramientas muy simples que podés usar para generar los dichosos Dockerfile.

    Te presento algunas.

    Devilbox

    http://devilbox.org/ te permite crear un entorno moderno y altamente personalizado con soporte para LAMP sobre docker.

    Su instalación es sencilla:

    git clone https://github.com/cytopia/devilbox
    cd devilbox
    cp env-example .env
    docker-compose up

    Y listo.

    En tus manos un LAMP con Redis, Memcached, MongoDB, phpMyAdmin y un montón de herramientas de administración disponibles en http://localhost para hacer todo bien fácil.

    Ah, y claro, si querés ver qué hay detrás de la magia, el archivo docker-compose.yml está a tu disposición en el directorio donde clonaste el repo.

    PHPDocker

    https://phpdocker.io/ es un sitio donde podés, a través de un wizard, configurar la imagen Docker que querés generar:

    Una vez tenés todo donde debe estar descargás el archivo comprimido, lo descomprimís en el directorio que más te guste, docker-compose up y, voilá, tu entorno php Dockerizado está disponible con todos los condimentos que hayas seleccionado.

    Sail

    Sail es una herramienta perteneciente al framework Laravel. Si creas una nueva aplicación desde cero no tendrás más que ejecutar ./vendor/bin/sail up dentro del directorio raíz de tu proyecto para comenzar.

    Una vez descargado y configurado todo podrás entrar en http://localhost y disfrtuar de tu nuevo entorno de trabajo con Docker.

    Y, como siempre, el archivo docker-compose.yml estará allí para investigar/modificar.

    Y un par más…

    Un par de herramientas más que vale la pena conocer son:

    • Deck: una aplicación de escritorio basada en electron.js con la que puedes crear un ambiente entero para desarrollo. La iba a incluir en este listado pero al probarla falló la instalación… tal vez más adelante cuando esté más madura la agregue.
    • Las imágenes de ServerSideUp optimizadas para ir a producción.

    Ahora sí, todo listo para dockerizar tus aplicaciones!

  • 8 razones por las que falla una aplicación PHP

    Es una historia que se repite una y otra vez: el sistema funciona perfecto en tu XAMPP pero cuando lo subís al hosting misteriosamente nadie puede registrarse ni logearse.

    Es el mismo codigo en el webserver y en localhost, no entiendo por qué da error en uno sí y otro no

    Dentro de xampp no me presenta problema, sólo en el hosting

    Estoy trabajando con laravel y estoy tratando de generar un sitemap.xml automatico, pero cuando lo genero no me lo guarda en la carpeta publica, solo logre que me lo guarde en el raiz del cpanel y no puedo hacer que me lo genere dentro del public_html

    ¿Qué pasó? El código es exactamente el mismo, lo viste funcionar con tus propios ojos.

    La única diferencia es que la URL, en lugar de empezar por http://localhost empieza por http://dominio.com, ¿cierto?

    Me temo que las diferencias pueden ir bastante más allá de eso.

    Para evitarte unas cuantas vueltas y dolores de cabeza te voy a contar las razones más frecuentes que llevan a este comportamiento.

    Intentaré ir de lo más frecuente hacia lo menos.

    Aquí voy.

    La versión de PHP

    La primera gran dependencia que toda aplicación php tiene es el propio intérprete.

    Si desarrollás en forma local tenés instalado algún paquete que permite transformar esto:

    <html>
      <body><p><?php echo "Hola mundo!"; ?></p></body>
    </html>

    En

    <html>
      <body><p>Hola mundo!"</p></body>
    </html>

    Generalmente esta responsabilidad le corresponde al servidor web que tenés instalado en tu computadora (¿XAMPP tal vez?).

    En tu hosting hay otro servidor web con una configuración similar pero no necesariamente idéntica.

    PHP es un lenguaje que está en constante evolución, año a año salen nuevas versiones y, si bien se hace un esfuerzo muy grande por mantener la compatibilidad con versiones viejas, esto no siempre se logra.

    Es por eso que algunas cosas que funcionan en una versión dejan de funcionar en las siguientes.

    En conclusión: lo primero que deberías verificar es que tu versión de PHP local es igual a la que tiene tu hosting.

    El archivo php.ini

    Además del intérprete, php dispone de un archivo de configuración especial: php.ini.

    En este archivo se definen ciertos parámetros que determinan detalles de cómo el intérprete realiza esa transformación.

    Las variables que pueden configurarse a través de este archivo son ciertamente muchas. Algunas son más críticas que otras.

    Un ejemplo muy simple es el de la directiva short_open_tag. Si su valor es "1" php no tendrá problemas en interpretar algo como:

    <html>
      <body><p><? echo "Hola mundo!"; ?></p></body>
    </html>

    Sin embargo, si este no es el caso, php dejará el texto tal como está, con lo cual, en lugar de transformarlo al HTML que esperás, el visitante de tu sitio verá el código.

    En conclusión: si las cosas no funcionan vale la pena comparar los cotenidos de tu php.ini y los de tu hosting.

    Las extensiones php

    PHP como tal trae una cantidad de funcionalidad incorporada pero es muy común que ciertas funciones se dejen como opcionales por razones de eficiencia.

    Para esos casos en los que se necesitan funcionalidades extras, php cuenta con el mecanismo de extensiones.

    Si tu aplicación depende de alguna en particular, por ejemplo si necesita generar gráficos, es muy probable que requiera de la presencia de una extensión en particular en el ambiente de ejecución.

    Si tu hosting no tiene instalada dicha extensión las cosas no van a funcionar como lo esperás.

    En conclusión: verificá si tu aplicación requiere alguna extensión especial y, en tal caso, asegurate de que esté presente en tu hosting.

    Los permisos

    Para que una aplicación php pueda ejecutarse es preciso que el usuario que ejecuta el servidor web tenga ciertos permisos sobre el sistema de archivos.

    Como mínimo, debe ser capaz de leer los archivos .php que componen tu aplicación.

    En muchos casos también será necesario que pueda escribir en ciertos directorios.

    En conclusión: validá que el usuario que ejecuta el webserver tenga los permisos necesarios para realizar las tareas que debe.

    La topología de red

    Típicamente cuando desarrollas en forma local la red donde tu aplicación vive es bastante sencillita: sólo existe localhost.

    Esto quiere decir que todos los servicios de los que depende son accesibles a través de la dirección de red 127.0.0.1 (O el nombre localhost, lo que es lo mismo).

    Más en concreto, si tu aplicación usa un MySQL como base de datos, es casi seguro que en algún lugar de tu código habrá una línea que se parece a:

    $link = mysqli_connect("127.0.0.1", "mi_usuario", "mi_contraseña", "mi_bd");

    Y esto funcionará sin problemas.

    El tema es que, en un entorno de hosting compartido donde hay muchos sitios hosteados en una misma computadora, es muy común que los servicios estén distribuidos en diferentes nodos de la red del proveedor.

    Esto quiere decir que, al intentar conectar al servidor de MySQL a través de la dirección 127.0.0.1 se producirá un fallo.

    En conclusión: verifica que las conexiones a servicios satélites se estén realizando utilizando las direcciones que correspnden a la red de tu hosting.

    Las rutas absolutas

    Un problema similar al anterior se da cuando se utilizan rutas absolutas.

    Por ejemplo:

    <?php
    
    require_once '/var/www/html/libreria.php';

    Puede funcionar en tu computadora porque existe en tu disco un archivo llamado libreria.php en un directorio /var/www/html/

    Si bien es posible que dicho directorio exista también en tu hosting, es bastante probable que no sea así.

    Si ese archivo está dentro del árbol de directorios de tu aplicación, una mejor forma de lograr el mismo objetivo es utilizar rutas relativas:

    <?php
    
    require_once __DIR__.'/libreria.php';

    En conclusión: usá rutas relativas en lugar de absolutas.

    La configuración del Apache

    Otro elemento que puede afectar negativamente al funcionamiento de la aplicación es la configuración del servidor web. No es que necesariamente se trate a Apache pero lo más probable es que así sea, especialmente en un ambiente de hosting compartido.

    Estas directivas afectan la forma en que el servidor web atiende los pedidos de tus visitantes.

    Muchas aplicaciones php dependen de ciertas configuraciones existentes en el archivo .htaccess (Reglas de re-escritura por ejemplo).

    Para que esto funcione, el webserver debe tener habilitado el procesamiento de este tipo de archivos

    En conclusión: valida que la configuración de tu Apache coincida con la de tu hosting.

    El sistema operativo

    El último de los sospechosos, que muchas veces es pasado por alto, es el sistema operativo sobre el que está montado el servidor.

    Si estás desarrollando en Windows y tu hosting es un Linux hay buenas chances de que no todo funcione a la primera.

    La diferencia para referenciar archivos (Cosas como c:\progams\file.php vs. /var/www/html/file.php) o el hecho de que para Linux un archivo llamado file.php no es el mismo que File.php mientras que para Windows sí son sólo algunas de las sutiles diferencias que pueden darte la idea de que el sistema está listo para subirse cuando en realidad estás a punto de abrir la caja de Pandora.

    En conclusión: verificá que tu código no dependa de características particulares de un sistema operativo.

    Cómo usar esta información

    A lo largo de este post te conté las razones que más comúnmente hacen que un despliegue de una aplicación PHP sea más traumático de lo que debería.

    Ahora que las conocés te recomiendo que las revises nuevamente y las uses a modo de lista de verificación para planificar tus próximas entregas.

  • Cómo ejecutar varias versiones de PHP en mismo NginX

    Cómo ejecutar varias versiones de PHP en mismo NginX

    Trabajando con un cliente me encontré ante este escenario:

    En un mismo servidor (Una instancia de AWS) había una aplicación desarrollada usando CodeIgniter y otra basada en Symfony.

    Al momento de comenzar mi intervención ambas aplicaciones compartían un mismo servidor web (NginX) y el binario de php para ejecutar algunos scripts de línea de comandos.

    El problema era que la versión de CodeIgniter en la que se había realizado el desarrollo (2.2.6) no podía actualizarse a la más reciente (4.1.5) sin re-escribir casi por completo la aplicación.

    Mientras tanto, la aplicación Symfony fue siguiendo la evolución del framework bastante de cerca.

    Para continuar el mantenimiento de la aplicación Symfony, y aprovechar nuevas caracterísitcas de rendimiento y seguridad, se hacía conveniente actualizar la versión de PHP y, difícilmente este cambio sería soportado por la aplicación vieja.

    La mejor solución sería darle a cada aplicación su propio entorno de ejecución de modo de que ninguna se vuelva un cuello de botella para la otra.

    La decisión fue mantener ambas versiones del lenguaje disponibles y que cada sitio utilizara la que le correspondiera (Al menos hasta definir qué hacer con la aplicación CodeIgniter).

    Pensé en pasar ambas a Docker y no descarto hacerlo más adelante pero, por el momento, me pareció demasiado esfuerzo para poco beneficio.

    Para tener dos versiones diferentes de PHP ejecutando en un mismo servidor es necesario:

    1. Instalar la nueva versión
    2. Modificar la configuración del WebServer
    3. Modificar la configuración de los cronjobs

    Cómo instalar una nueva versión de PHP

    El servidor en cuestión es un Ubuntu, de modo que instalar una nueva versión de PHP (8.0 en mi caso) requiere estos comandos:

    sudo add-apt-repository ppa:ondrej/php
    sudo apt install php8.0

    Con esto queda instalado el binario de php en su versión 8, luego hay que tener en cuenta instalar las extensiones que sean necesarias.

    Una vez finalizado el proceso, con este comando:

    update-alternatives --display php

    Vemos que se ha instalado la nueva versión:

    php - manual mode
      link best version is /usr/bin/php8.0
      link currently points to /usr/bin/php7.3
      link php is /usr/bin/php
      slave php.1.gz is /usr/share/man/man1/php.1.gz
    /usr/bin/php7.3 - priority 73
      slave php.1.gz: /usr/share/man/man1/php7.3.1.gz
    /usr/bin/php8.0 - priority 80
      slave php.1.gz: /usr/share/man/man1/php8.0.1.gz

    Notá como el comando php es un link simbólico que está alojado en /usr/bin/php y apunta a /usr/bin/php7.3. Es por eso que php -v muestra:

    PHP 7.3.19-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Jun 12 2020 07:48:30) ( NTS )
    Copyright (c) 1997-2018 The PHP Group
    Zend Engine v3.3.19, Copyright (c) 1998-2018 Zend Technologies
        with Zend OPcache v7.3.19-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

    Es decir, si queremos asegurarnos de estar ejecutando la versión 8.0 el comando que nos da más certeza es /usr/bin/php8.0 -v:

    PHP 8.0.13 (cli) (built: Nov 22 2021 09:50:24) ( NTS )
    Copyright (c) The PHP Group
    Zend Engine v4.0.13, Copyright (c) Zend Technologies
        with Zend OPcache v8.0.13, Copyright (c), by Zend Technologies 

    Perfecto. Tengamos esto en cuenta para dentro de un rato cuando veamos lo que pasa con los cronjobs.

    Cómo especificar la versión de PHP para cada sitio

    Para este punto viene muy bien el hecho de estar usando NginX como servidor web. A diferencia de Apache que puede tener PHP incorporado, NginX se limita a servir contenido estático y delega la ejecución de PHP en otro proceso (php-fpm).

    Si miramos el archivo de configuración de cada sitio veremos algo como:

    server {
        ...
        location ~ ^/index\.php(/|$) {
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    
            fastcgi_intercept_errors off;
            fastcgi_buffer_size 16k;
            fastcgi_buffers 4 16k;
        }
    
        ...
    }

    En particular la línea que nos interesa en este caso es:

    fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;

    Aquí se está definiendo el canal de comunicación entre el servidor web y el proceso que atenderá las peticiones php.

    De modo que lo que debemos cambiar es el 7.3 por 8.0 en el archivo que corresponde a la aplicación más nueva.

    Claro que, para que esto funcione debemos contar con php8.0-fpm.

    Para instalarlo puede usarse el comando:

    sudo apt install php8.0-fpm

    Y con eso ya contaremos con el proceso FastCGI que necesitamos.

    Por supuesto que, antes de aplicar estos cambios en producción es prudente realizar pruebas en un ambiente controlado. Asumiendo que ya se realizaron dichas pruebas y se corrigieron eventuales inconvenientes, con los cambios realizados la aplicación web está lista.

    Resta ver qué hacer con las tareas programadas y/o scripts de línea de comandos que se utilicen.

    En este caso lo que hay son algunas tareas programadas vía cron.

    Cómo especificar la versión de PHP para cada cronjob

    Usando el comando crontab -l obtenemos algo como:

    # Edit this file to introduce tasks to be run by cron.
    # 
    # Each task to run has to be defined through a single line
    # indicating with different fields when the task will be run
    # and what command to run for the task
    # 
    # To define the time you can provide concrete values for
    # minute (m), hour (h), day of month (dom), month (mon),
    # and day of week (dow) or use '*' in these fields (for 'any').# 
    # Notice that tasks will be started based on the cron's system
    # daemon's notion of time and timezones.
    # 
    # Output of the crontab jobs (including errors) is sent through
    # email to the user the crontab file belongs to (unless redirected).
    # 
    # For example, you can run a backup of all your user accounts
    # at 5 a.m every week with:
    # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
    # 
    # For more information see the manual pages of crontab(5) and cron(8)
    # 
    # m h  dom mon dow   command
    
    MAILTO=mauro.chojrin@leewayweb.com
    0 6 1 2,5,8,11 * /usr/bin/php /home/ubuntu/followapp/bin/console app:agents:send-transaction-summary

    Esto significa que todos los 1 de los meses de Febrero, Mayo, Agosto y Noviembre a las 6:00 AM se ejecuta el script PHP /home/ubuntu/followapp/bin/console pasándole como argumentos app:agents:send-transaction-summary.

    El script es el que Symfony dispone para la ejecución de comandos diseñados utilizando el framework.

    El argumento especifica cuál de todos los comandos disponibles es el que se desea ejecutar (En este caso se trata de uno diseñado a efectos de enviar a los vendedores un resumen de las transacciones realizadas durante el trimestre anterior).

    Y la parte de la línea que dice /usr/bin/php es la que especifica cuál será el binario que deberá invocarse cuando sea el momento indicado. En este caso se trata del binario de PHP.

    Claro que, en este servidor donde hay más de una versión de PHP, esta definición puede resultar ambigua (A los ojos humanos claro, para la computadora está muy claro que /usr/bin/php es un alias de /usr/bin/php7.3).

    Lo conveniente para evitar confusiones es hacer explícita la versión del intérprete que se requiere, dejando la línea del crontab de esta forma:

    0 6 1 2,5,8,11 * /usr/bin/php /home/ubuntu/followapp/bin/console app:agents:send-transaction-summary

    Y ahora sí, con este último cambio está todo listo para tener ambas versiones conviviendo en armonía.

    Unas últimas notas

    Como habrás podido apreciar, no es realmente complejo lograr esta configuración, sin embargo, siendo que el servidor ya se encuentra virtualizado, lo más conveniente sería tener una instancia separada para cada aplicación.

    La desventaja de este enfoque es que, además de los costos propios de la infraestructura, la administración puede hacerse un poco más compleja.

    Lo que debe evaluarse para decidir es el riesgo de que una aplicación falle y, al competir por los recursos con la otra, deje fuera de línea un sitio que, en principio, podría continuar operativo.

  • Cómo usar Docker en proyectos PHP

    Cómo usar Docker en proyectos PHP

    Hace tiempo que vengo usando (¡y abogando por su uso!) máquinas virtuales para mis proyectos PHP.

    Hasta ahora me venía manejando con Vagrant y debo decir que me ha dado unas cuantas satisfacciones.

    Sin embargo, hay algunos problemas derivados de su uso:

    1. Las VM se pueden volver muy pesadas
      • Ocupan mucho espacio en el disco
      • Son lentas de levantar
      • No es sencillo tener muchas corriendo a la par (Consumen muchos recursos de hardware)
    2. No es fácil asegurarme de que en Producción y en Desarrollo tengo exactamente el mismo software instalado.

    Investigando un poco y, hay que decirlo también, por consejo de algunos colegas me metí con docker.

    Qué es Docker

    Docker es una herramienta de virtualización basada en un concepto algo diferente al que usa Vagrant: los contenedores.

    No me voy a meter acá en los detalles técnicos, simplemente diré que un contenedor hace un uso mucho más eficiente de los recursos del hardware y, a los fines prácticos, cumple la misma función que una VM.

    Cómo se usa Docker

    Docker se basa en el docker daemon corriendo constantemente y luego en un cliente que le envía comandos.

    Lo primero que necesitás es tener algún contenedor levantado… y para eso, lo primero que necesitás es tener algún contenedor creado.

    Los contenedores se crean en base a imágenes.

    Qué es una imagen de Docker

    Una imagen de docker es una definición de un entorno de ejecución completo (algo así como una VM de Vagrant).

    Un contenedor es una imagen en ejecución.

    Podrías pensarlo como la diferencia entre un programa y un proceso.

    Las imágenes docker se definen en un archivo de texto llamado Dockerfile (Bastante similar al Vagrantfile).

    Por ejemplo:

    FROM php:7.2-cli
    COPY . /usr/src/myapp
    WORKDIR /usr/src/myapp
    CMD [ "php", "./your-script.php" ]

    Lo que ves es una serie de instrucciones.

    La primera (FROM) es tal vez la más importante: la imagen base.

    Las imágenes docker manejan un concepto similar al de la herencia de POO: Sobre una imagen base es posible crear otras más especializadas.

    Para efectivamente arrancar esta imagen debemos crear un contenedor basado en ella.

    Antes de hacer eso es conveniente crear un archivo llamado your-script.php (Es importante hacerlo antes de crear el contenedor porque el comando COPY se ejecutará durante la creación y no volverá a ejecutarse hasta que el contenedor sea destruido y vuelto a crear).

    En cierto sentido, esto es como quemar una ROM 🙂

    Pues entonces, creemos un archivo your-script.php con este contenido:

    <?php
    
    echo "Estoy en docker!!".PHP_EOL;

    Y ahora sí ¡estamos listos para darle vida a nuestro primer contenedor docker!

    sudo docker build -t my-php-app .

    Con este comando hemos creado nuestro contenedor.

    Para ejecutar algún comando dentro de él usaremos:

    sudo docker run -it --rm --name my-running-app my-php-app

    Y obtendremos la salida:

    Estoy en docker!!

    Cómo correr una aplicación web PHP en docker

    Típicamente para ejecutar una aplicación web PHP vas a necesitar al menos un servidor web y el intérprete de PHP instalado.

    Podrías definir tu propia imagen instalando todos los paquetes y demás, pero… ¿vale realmente la pena?

    No.

    Puedes basar tu imagen en una que ya tenga un poco más allanado el camino.

    Por ejemplo php:7.3-apache está basada en Ubutu 18.04 y ya trae php 7.3, Apache y algún par de utilidades más.

    De modo que usando un Dockerfile como este:

    FROM php:7.3-apache
    COPY . /var/www/html/

    Podremos tener un contenedor que incluya un Apache y nuestro código en el DocumentRoot.

    Un detalle importante que falta es «avisar» a docker que queremos que nuestro contenedor pueda ser accedido desde afuera a través del puerto 80 (Muy parecido al mapeo de puertos que se usa en Vagrant).

    Para eso vamos a usar el comando EXPOSE. El Dockerfile se verá así:

    FROM php:7.3-apache
    COPY . /var/www/html/
    EXPOSE 80

    Para no complicar mucho las cosas renombremos el archivo your-script.php a index.php y usemos este comando para crear nuestro contenedor:

    sudo docker build -t my-php-web-app .

    Para entrar a ver nuestro flamante sitio tenemos que ejecutar:

    sudo docker run -p 80:80 --rm -it --name my-web-app my-php-web-app:latest

    Y, por supuesto, abrir un navegador en http://localhost.

    Si todo salió bien deberías ver algo como:

    Cómo desplegar una imagen Docker en Producción

    Muy bien, ya tenemos todo casi listo, sólo nos falta ver cómo desplegar nuestra imagen en un servidor de producción y concluimos.

    Claramente, esta es la parte que realmente hace una diferencia respecto de usar Vagrant… difícilmente vas a querer montar una VM en un servidor productivo por cada aplicación que tengas… o vas a tener una factura bien abultada en AWS.

    Existen varias opciones para realizar el despliegue. Para mantener este artículo dentro de un alcance acotado me voy a limitar a la que considero requiere menos conocimientos extra:

    1. Grabar la imagen en nuestra máquina local
    sudo docker save -o image.zip my-php-web-app
    1. Subir la imagen al servidor de producción
    scp image.zip <user>@<server-addres>:<target-location>
    1. Agregar la imagen al repositorio de docker
    docker load -i <path-to-image.zip>
    1. Crear el contenedor a partir de la imagen
    docker run -d -p 8888:80 my-php-web-app

    Y listo! Ahora se puede acceder a la aplicación entrando a la dirección pública del servidor y el puerto 8888 (Y si es tu única webapp podrías directamente mapear el puerto 80 de tu servidor al del contenedor).

  • Qué se necesita para poner online una aplicación PHP

    Qué se necesita para poner online una aplicación PHP

    Una pregunta que parece algo obvia, ¿no? Lo que se necesita para poner en línea una aplicación PHP es un hosting. No hay mucho más que decir al respecto, ¿cierto? Pues… tal vez convenga hilar un poco más fino.

    Si bien en sus inicios PHP se utilizaba exclusivamente para la creación de aplicaciones web, hoy en día abarca un abanico mucho más amplio.

    En este artículo me centraré en la infraestructura mínima necesaria para poner en línea una aplicación web desarrollada con PHP.

    Qué debe tener un servidor para hostear una aplicación PHP

    Lo primero que debemos comprender es que, para que una aplicación web esté en línea, independientemente del lenguaje en que esté desarrollada, se requiere:

    1. Que el código esté disponible en alguna computadora conectada a Internet (El Servidor)
    2. Que dicha computadora cuente con algún software capaz de recibir peticiones a través de Internet (El WebServer) instalado y funcionando
    3. Que la dirección IP de esa computadora sea conocida en forma pública (o fácilmente averiguable)

    En el caso de PHP un requisito adicional es que esté presente en el servidor un software capaz de interpretar y ejecutar el código (El intérprete).

    Existen muchas combinaciones diferentes de software que se encargan de esto, entre las más conocidas podemos encontrar:

    Incluso es posible utilizar el Internet Information Server si el sistema operativo del servidor es Windows.

    Luego será necesario configurar el servidor web de modo que ciertas peticiones sean derivadas al intérprete de php (A diferencia de otras que simplemente deben ser servidas enviando el contenido de los archivos solicitados).

    Esta configuración es diferente según el paquete de software con que se cuente.

    Qué servicios aparte del hosting se necesitan para poner online una aplicación PHP

    Usualmente, cuando se desea poner un sitio en línea, se busca que los visitantes accedan al mismo a través de una dirección sencilla de recordar (Lo que se conoce como un dominio), sin embargo, para que la computadora cliente pueda conectarse a la computadora servidor es necesario conocer su dirección IP.

    Para ello existe un servicio adicional: el DNS.

    De modo que, para que nuestro sitio esté disponible al público será necesario, además de registrar un dominio, configurar el DNS para que realice esa traducción.

    Luego, dependiendo de las necesidades específicas del sitio que queremos montar, es probable que sea necesaria la instalación de algún software de gestión de bases de datos (Como MySQL, PostGre o alguno similar).

    Respecto de la computadora que actuará como servidor, existen diferentes opciones (de diferentes costos y requisitos técnicos).

    Se puede usar una computadora personal propia, contratar espacio en un servidor compartido, comprar una computadora y dejarla en un proveedor que garantice la alimentación y conectividad, usar un servidor virtual… en fin, las opciones son muchas.

    ¿Te cuesta decidir? Este post puede ayudarte.

  • Docker o VM ¿Cuál es mejor para PHP?

    Estás montando tu entorno de trabajo local para trabajar en un proyecto PHP.

    Hay muchas cosas por definir pero una es segura: no vas a usar XAMPP ni nada parecido… después del último fiasco fue suficiente, hay que virtualizar sí o sí.

    Y la pregunta es: ¿voy con Docker o con una VM?

    Creeme que te entiendo, estuve mucho tiempo en tus zapatos.

    Hoy por hoy mi elección es clara: Docker. Pero no te pido que me creas así sin más, dejame darte una breve explicación para que saques tu conclusión.

    En qué se parecen y en qué se diferencian Docker y las Máquinas Virtuales

    Docker es un sistema de administración de contenedores. Sin entrar en mucho detalle, diré que es un método para crear y administrar entornos de ejecución aislados del resto.

    Las máquinas virtuales son sistemas de simulación de hardware.

    ¿Entonces…?

    Las máquinas virtuales son, en cierta medida, más poderosas ya que permiten crear un entorno de computación «completamente» separado del host, donde puede instalarse, por ejemplo, un sistema operativo diferente de aquel del host.

    Docker (o algún otro sistema de contenedores) en cambio no virtualiza hardware, si no software. Esto significa que sus posibilidades son algo más limitadas (Por ejemplo, montar un contenedor Linux en un host Windows es algo que, en principio no es posible).

    Hasta aquí la balanza parece inclinarse hacia las VMs, ¿no? Entonces… ¿por qué deberías preferir Docker?

    Los contenedores Docker son mucho más livianos que las VMs. Esto implica que:

    • Se inician/frenan mucho más rápido
    • Ocupan mucho menos espacio en el disco
    • Consumen muchos menos recursos del host

    Todo esto hace que sea mucho más viable tener un gran número de contenedores Docker ejecutando en un mismo host, a diferencia de lo que ocurre con las máquinas virtuales.

    Dejando estos detalles de implementación de lado, en la práctica las diferencias son mínimas. Cambia un poco la forma de configurar el entorno pero ambos se prestan muy bien para la automatización.

    Tanto Docker como los sistemas de virtualización cuentan con interfaces de línea de comandos muy potentes y, sobre esas herramientas básicas se montan algunas más avanzadas (Vagrant para el caso de VMs y docker-compose para Docker) o incluso algunas con interface gráfica, lo cual facilita mucho su uso.

    De modo que, siendo que el costo de implementar una o la otra es prácticamente igual, ¿por qué ir con la que más recursos consume?

    Por supuesto que la realidad es más compleja, hay que analizar el caso por caso pero, en líneas generales, mi recomendación es ir con Docker.

    Cómo arrancar con Docker

    Bueno, este tema excede un poco el objetivo de este post, pero voy a intentar hacer un breve resúmen y dejarte algunas referencias que puedan ayudarte:

    1. Instalar Docker
    2. Buscar una imagen que puedas usar como prueba
    3. Crear un contenedor
    4. Correr el «Hola Mundo!» 🙂

    Esto es una visión muy reducida. Si querés más detalles te invito a leer este post.

    Y si ya diste tus primeros pasos pero tenés dudas, te recomiendo mirar la Guía Práctica de Dockerización de PHP.