Red de conocimiento informático - Conocimiento informático - Cómo configurar un entorno de desarrollo PHP para integración continua Dockerizada

Cómo configurar un entorno de desarrollo PHP para integración continua Dockerizada

Primero, debemos entender qué es un buen entorno de desarrollo. Para mí, un buen entorno de desarrollo debe tener las siguientes características:

Gratuito. Debo poder eliminar y crear nuevos entornos a voluntad.

Inicio rápido. Cuando quiero usarlo, está disponible inmediatamente.

Fácil de actualizar. Las cosas cambian muy rápidamente en nuestra industria, por lo que tengo que poder actualizar fácilmente mi entorno de desarrollo a nuevas versiones de software.

Y Docker admite todas estas funciones y más. Puede destruir y reconstruir contenedores casi instantáneamente, y actualizar su entorno es tan simple como reconstruir la imagen que está utilizando actualmente.

Qué es un entorno de desarrollo PHP

Debido a la complejidad de las aplicaciones web actuales, un entorno de desarrollo PHP requiere muchas cosas y es necesario establecer varias restricciones para mantener el entorno sencillo.

En esta ocasión utilizamos Nginx, PHP5-FPM y MySQL para ejecutar el proyecto Synmfony. Debido a la complejidad de ejecutar la línea de comando en un contenedor, dejaré este aspecto para la próxima publicación del blog.

Mascotas y vacas

Otro punto de discusión es si queremos implementar el entorno de desarrollo en múltiples contenedores o en un solo contenedor. Ambos enfoques tienen ventajas:

Un único contenedor es fácil de distribuir y mantener. Al ser independientes, todo se ejecuta en el mismo contenedor, que es como una máquina virtual. Pero esto también significa que cuando quieras actualizar algo (como una nueva versión de PHP), necesitarás reconstruir todo el contenedor.

Múltiples contenedores proporcionan una mejor modularidad al agregar componentes. Debido a que cada contenedor contiene parte de la pila: Web, PHP, MySQL, etc., cada servicio se puede ampliar o agregar individualmente sin tener que reconstruir todo.

Como soy vago y necesito algo más en mi portátil, lo haremos con un solo contenedor.

Inicializando el proyecto

Lo primero que debemos hacer es inicializar un nuevo proyecto Symfony. El método recomendado es utilizar el comando crear proyecto del compositor. También es posible instalar Composer en la estación de trabajo, pero es demasiado sencillo. Esta vez lo usaremos a través de Docker.

Anteriormente publiqué un artículo sobre los comandos de Docker: crear comandos de Docker (Está bien, mentí, originalmente lo puse en este artículo, pero luego pensé que era mejor enumerarlo por separado. Es mejor publicarlo). ).

De todos modos, puedes leerlo. A continuación, puedes crear tu propio alias de compositor si aún no tienes uno.

$ alias compositor="docker run -i -t -v \$PWD:/srv ubermuda/composer"

Ahora puedes inicializar el proyecto Symfony:

$ compositor crear-proyecto symfony/ framwork-standard-edition SomeProject

¡Impresionante! Comienza el verdadero trabajo. (Un montón de tonterías ensimismadas omitidas en el blog.... Texto original: Genial. Choca esos cinco, toma una taza de café o el remedio líquido que prefieras y prepárate para ponerte manos a la obra.)

Contenedor

Construir un contenedor independiente que ejecute un proyecto estándar de Symfony es muy fácil de construir.

Todo lo que necesita hacer es instalar los habituales Nginx, PHP5-FPM y MySQL-Server, colocar los archivos de configuración del host virtual Nginx preparados previamente, copiar algunos archivos de configuración y listo.

El código fuente del contenedor se encuentra en el repositorio ubermuda/docker-symfony en GitHub. Dockerfile es el archivo de configuración utilizado por Docker para crear imágenes, echemos un vistazo:

De Debian: wheezy

ENV DEBIAN_FRONTEND no interactivo

EJECUTAR apt-get update -y

EJECUTAR apt-get install -y nginx php5-fpm php5-mysqlnd php5-cli mysql-server supervisor

EJECUTAR sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/ php5/fpm/php-fpm.group/listen.group/' -i /etc/php5/fpm/pool.d/www.conf

EJECUTAR sed -e 's/ ;escuchar\.owner/listen.owner/' -i /etc/php5/fpm/pool.d/www.conf

EJECUTAR echo "\ndaemon off;" /nginx.conf

AÑADIR vhost.conf /etc/nginx/sites-available/default

AÑADIR supervisor.conf /etc/supervisor/conf.d/supervisor.conf

AÑADIR init.sh /init.sh

EXPOSE 80 3306

VOLUMEN ["/srv"]

WORKDIR /srv

CMD["/usr/bin/supervisord"]

Primero ampliamos la imagen base debian:wheezy y luego usamos una serie de comandos sed para configurar Nginx y PHP5-FPM.

EJECUTAR sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf

EJECUTAR sed -e ' s/;listen\.owner /listen.owner/' -i /etc/php5/fpm/pool.d/www.

EJECUTAR sed -e 's/;listen\.group/listen. grupo/' -i /etc/php5/fpm/pool.d/www.conf

EJECUTAR echo "\ndaemon off;" gt;gt;

Aquí tenemos que hacer dos cosas. Primero, configure PHP5-FPM y Nginx para que se ejecuten en primer plano para que el supervisor pueda rastrearlos.

Luego, configure PHP5-FPM para ejecutar el servidor web como el usuario especificado, prestando atención a los permisos de los archivos.

A continuación, debe instalar un conjunto de archivos de configuración, comenzando con el archivo de configuración del host virtual de Nginx, vhost.conf:

servidor {

escucha 80 <; /p>

nombre_servidor _;

access_log /var/log/nginx /access.log;

error_log /var/log/nginx/error.log; >

raíz /srv/web;

índice app_dev.php;

ubicación / {

try_files $uri $uri/ /app_dev.php? $query_string

}

ubicación ~ [^/]\.php(/|$) {

fastcgi_pass unix:/var/run/php5- fpm.sock;

incluye fastcgi_params;

}

}

Como no necesitamos un nombre de dominio, configuramos server_name a _ (Algo similar a la variable de marcador de posición $_ de Perl) y configure el directorio raíz (directorio raíz de documentos) en /srvr/web. Implementaremos la aplicación en /srv y el resto es una configuración estándar PHP5-FPM de Mginx.

Dado que el contenedor solo puede ejecutar un programa a la vez, necesitamos usar supervisord (o cualquier otro administrador de procesos, pero prefiero usar supervisord). ¡Afortunadamente, este administrador de procesos generará todos los procesos que necesitamos! php5-fpm]

command=/usr/sbin/php5-fpm

[programa: mysql]

command=/usr/bin/mysqld_safe p>

[programa:init]

command=/init.

autorestart=false

redirect_stderr=true

redirect_stdout =/srv/app/logs/init.log

Lo que debemos hacer aquí es definir todos los servicios y un programa especial: el proceso de inicio. Este proceso no es un servicio real, pero se ejecuta. el script de inicio. Una forma primitiva.

El problema con este script de inicio es que normalmente requiere que algunos servicios se inicien primero. Por ejemplo, es posible que desee inicializar algunas tablas de la base de datos, pero sólo después de ejecutar MySQL primero. Una posible solución es iniciar MySQL en el script de inicio, luego inicializar las tablas, luego, para evitar interferencias con la gestión de procesos del supervisor, detener MySQL y finalmente iniciar supervisor.

Un script de este tipo tendría el siguiente aspecto:

/etc/init.d/mysql start

app/console doctrina:schema:update --force

/etc/init.d/mysql stop

exec/usr/bin/supervisord

Se ve feo, hagamos lo contrario, dejemos que el supervisor se ejecute y nunca reiniciarlo.

El script init.sh real tiene este aspecto:

#! /bin/bash

RET=1

mientras [[ RET -ne 0 ]]]; hacer

dormir 1;

mysql -e 'salir' gt; /dev/null 2gt; amp; RET=$?

hecho

DB_NAME=${DB_NAME:-symfony}

mysqladmin -u root crea $DB_NAME

si [ -n "$INIT" ] entonces

/srv/$INIT

fi

El script espera a que se inicie MySQL, luego crea la base de datos basada en la variable de entorno DB_NAME (el valor predeterminado es Symfony), luego busca el script para ejecutar en la variable de entorno INIT e intenta ejecutarlo. Al final de este artículo se explica cómo utilizar estas variables de entorno.

Crear y ejecutar imágenes

Comenzar es difícil. También necesitamos construir la imagen de Symfony Docker usando el comando docker build:

$ cd docker-symfony

$ docker build -t symfony.

Ahora Puedes usarlo para ejecutar tu proyecto Symfony:

$ cd SomeProject

$ docker run -i -t -P -v $PWD:/srv symfony

Veamos qué hace esta lista de opciones:

-i inicia el modo interactivo, lo que significa que STDIO (entrada y salida estándar) se conectará a su terminal actual. Es útil cuando desea recibir registros o enviar señales a un proceso.

-t crea un TTY virtual para el contenedor, generalmente usado junto con -i.

-P le dice al demonio Docker que anuncie todos los puertos especificados, en este caso el puerto 80.

-v $PWD:/srv Monta el directorio actual en el directorio /srv del contenedor. Montar un directorio hace que el contenido del directorio esté disponible en el punto de montaje de destino.

Ahora todavía recuerdas las variables de entorno DB_NAME e INIT mencionadas anteriormente, su función es: personalizar el entorno. Básicamente, puedes usar la opción -e de Docker Run para establecer variables de entorno en el contenedor y el script de inicio las recogerá, por lo que si tu base de datos se llama some_project_dev, puedes ejecutar el contenedor de esta manera:

$ docker run -i -t -P -v $PWD:/srv -e DB_NAME= some_project_dev Symfony

La variable de entorno INIT es más poderosa y le permite ejecutar un script específico al inicio.

Por ejemplo, tiene un script bin/setup que ejecuta el comando de instalación del compositor y establece el esquema de la base de datos:

#! /bin/bash

instalación del compositor

aplicación/consola doctrina:schema:update --force

Ejecutar con -e:

$ ventana acoplable ejecutar -i -t -P \

-v $PWD:/srv \

-e DB_NAME=some_project_dev \

-e INIT=bin /setup

Tenga en cuenta que la opción -e se puede usar varias veces en una ejecución de Docker y se ve bien. Además, el script de inicio requiere permisos ejecutables (chmod x).

Ahora, enviemos una solicitud al contenedor mediante curl para comprobar que todo está funcionando como se esperaba. Primero, necesitamos usar el comando docker port para obtener el puerto público **** asignado por Docker al puerto 80 del contenedor:

$ docker port $(docker ps -aql 1) 80

0.0 .0.0: 49153

docker ps -aql 1 es un buen comando para usar. En nuestro ejemplo, Docker asigna el puerto 80 del contenedor al puerto 49153. En nuestro ejemplo, Docker asigna el puerto 80 del contenedor al puerto 49153. Corramos curl y veamos.

$ curl http://localhost:49153

No puedes acceder al archivo. Consulte app_dev.php para obtener más información.

Cuando no obtenemos la identificación del contenedor de localhost, la identificación del contenedor se asignará al puerto 49153.

Cuando no obtenemos la identificación del contenedor de localhost, la identificación del contenedor se asignará al puerto 49153. (Es completamente normal recibir el mensaje de error predeterminado de Symfony sin acceder al controlador de desarrollo desde localhost, ya que no enviamos solicitudes curl desde el interior del contenedor, por lo que eliminar estas líneas del controlador de front-end web/app_dev.php es seguro.

// Esta verificación evita que el controlador frontal de depuración se implemente accidentalmente en el servidor de producción.

// No dude en eliminarlo, ampliarlo o crear una funcionalidad más compleja.

if (isset($_SERVER['HTTP_CLIENT_IP'])

|| isset($_SERVER['HTTP_X_FORWARDED_FOR '])

|| !( in_array (@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1'))|| php_sapi_name() === 'cli-server')

){

header(' HTTP/1.0 403 Prohibido');

exit('No tienes permiso para acceder a este archivo. Para obtener más información, consulta'. basename(__FILE__).');

}

Estas líneas impiden cualquier acceso al controlador de desarrollo desde fuera de localhost.

Ahora usa curl nuevamente o usa tu navegador para visitar http://localhost:.49153/:

Eso es fácil, ¿verdad? Ahora podemos activar y actualizar entornos rápidamente, pero todavía hay mucho margen de mejora.