Hoy día es una necesidad para los desarrolladores contar con un entorno de desarrollo y pruebas basado en Linux lo mas similar posible a un entorno de producción y lo suficientemente flexible para soportar una variedad de herramientas, no solo el stack Apache, PHP y MySQL.
También se hace necesario utilizar otros como Nginx, Python o NodeJS solo por nombrar algunos, para utilizar estas herramientas en un entrono de desarrollo una de las herramientas mas flexibles y populares es Docker.
En este articulo vamos a crear un contenedor con Nginx como servidor web y con soporte para Multi PHP que nos permitira trabajar con diferentes proyectos en el mismo contenedor y cada uno con una version de PHP diferente, para cada sitio pudiendo escoger para cada sitio una las siete versiones de PHP disponibles.
Versiones de PHP que instalaremos
Vamos a instalar las siguientes versiones de PHP en el mismo contenedor
- PHP 5.4
- PHP 5.5
- PHP 5.6
- PHP 7.0
- PHP 7.1
- PHP 7.2
- PHP 7.3
Contents
Preparación de las Imágenes
Primera Imagen (PasoUno)
Lo primero va a ser cear un contenedor que corra CentOS e instalar un paquete, específicamente initscripts este paquete es importante para no tener problemas con el comando systemctl a la hora de controlar servicios:
docker run -it --privileged -e "container=docker" --cap-add SYS_ADMIN \ --tmpfs /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ --name PasoUno "centos:latest" "/bin/bash"
Si intentáramos ver iniciar, detener, reiniciar o simplemente ver el estado de un servicio como dbus nos saltara el siguiente mensaje:
[root@e8c87e7efdd4 /]# systemctl status dbus Failed to get D-Bus connection: Operation not permitted [root@e8c87e7efdd4 /]#
Para solucionar esto anterior en el siguiente paso instalamos initscripts y ademas asignamos una contraseña al usuario root debido a que la imagen original de centos en docker no tiene password debido a que directamente se ejecuta bash
Ahora en adelante necesitaremos que tenga contraseña para poder logearnos mediante init, por defecto le estoy colocando docker como password, ustedes pueden configurar el que quieran
#Actualizamos la imagen yum -y update #Instalamos el paquete necesario yum install -y initscripts #Asignamos una contraseña al root, en este caso docker echo "docker" | passwd root --stdin #Esto solo para que no de error al iniciar touch /etc/sysconfig/network #Salimos exit
Convertimos el Contenedor en Imagen
Con docker ps -a podemos listar los contenedores, aqui veremos que ya nos aparece el contenedor llamado PasoUno que creamos anteriormente:
alvaro@acer:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e60ca0603d26 centos:latest "/bin/bash" 2 minutes ago Exited (0) 20 seconds ago PasoUno
En el comando anterior vemos que el contenedor con nombre PasoUno tiene un ID e60ca0603d26, por supuesto este id va a ser diferente en tu pc, copias el que aparezca a ti y ejecutas lo siguiente:
alvaro@acer:~$ docker commit e60ca0603d26 centos-base
En mi caso a la nueva imagen lo llame centos-base, ustedes pueden llamarlo como quieran.
Segunda Imagen (PasoDos)
En este paso crearemos un segundo contenedor a partir de la imagen centos-base, la diferencia con el primer contenedor es que esta vez el contenedor correrá /usr/sbin/init en lugar de /bin/bash , esta diferencia es fundamental porque los contenedores ya no tendrán el problema para iniciar servicios automáticamente.
docker run -it --privileged --hostname="server" -e "container=docker" --cap-add SYS_ADMIN \ --tmpfs /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -p 22:22 -p 80:80 -p 3306:3306 \ --name PasoDos "centos-base" "/usr/sbin/init"
Instalación del Stack Nginx+MySQL+ MutiPHP
Una vez que hayamos arrancado el nuevo contenedor en el paso anterior vamos a instalar unos cuantos paquetes y a configurarlo
#Instalamos este repositior yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install -y epel-release #Actualizamos el sistema yum update -y #Opcional: En lo personal instalo todos estas herramientas y #liberias porque siempre suelo utilizarlas yum install -y wget nano git iputils bind-utils net-tools nmap mtr gcc gcc-c++ make autoconf glibc rcs pcre-devel openssl-devel expat-devel geoip-devel zlib-devel mlocate ncdu mytop yum install yum-utils -y #Instalamos Nginx, MariaDB y SSH yum install -y httpd mariadb-server openssh-server nginx #Con esto instalaremos PHP 5.4, 5.5, 5.6, 7.0, 7.1, 7.2 y 7.3 #ademas de todas las librerías necesarias mas PHP-FPM para #cada versión de PHP anterior yum install -y php54 php55 php56 php70 php71 php72 php73 \ php54-php-fpm php55-php-fpm php56-php-fpm php70-php-fpm php71-php-fpm php72-php-fpm php73-php-fpm \ php54-php-mysql php54-php-mcrypt php54-php-mbstring php54-php-cli php54-php-fpm php54-php-gd php54-php-json php54-php-ioncube-loader php54-php-intl php54-php-pdo php54-php-pgsql php54-php-soap php54-php-xml php54-php-xmlrpc \ php55-php-mysql php55-php-mcrypt php55-php-mbstring php55-php-cli php55-php-fpm php55-php-gd php55-php-json php55-php-ioncube-loader php55-php-intl php55-php-pdo php55-php-pgsql php55-php-soap php55-php-xml php55-php-xmlrpc \ php56-php-mysql php56-php-mcrypt php56-php-mbstring php56-php-cli php56-php-fpm php56-php-gd php56-php-json php56-php-ioncube-loader php56-php-intl php56-php-pdo php56-php-pgsql php56-php-soap php56-php-xml php56-php-xmlrpc \ php70-php-mysql php70-php-mcrypt php70-php-mbstring php70-php-cli php70-php-fpm php70-php-gd php70-php-json php70-php-ioncube-loader php70-php-intl php70-php-pdo php70-php-pgsql php70-php-soap php70-php-xml php70-php-xmlrpc \ php71-php-mysql php71-php-mcrypt php71-php-mbstring php71-php-cli php71-php-fpm php71-php-gd php71-php-json php71-php-ioncube-loader php71-php-intl php71-php-pdo php71-php-pgsql php71-php-soap php71-php-xml php71-php-xmlrpc \ php72-php-mysql php72-php-mcrypt php72-php-mbstring php72-php-cli php72-php-fpm php72-php-gd php72-php-json php72-php-ioncube-loader php72-php-intl php72-php-pdo php72-php-pgsql php72-php-soap php72-php-xml php72-php-xmlrpc \ php73-php-mysql php73-php-mcrypt php73-php-mbstring php73-php-cli php73-php-fpm php73-php-gd php73-php-json php73-php-ioncube-loader php73-php-intl php73-php-pdo php73-php-pgsql php73-php-soap php73-php-xml php73-php-xmlrpc \ #Detenemos estos servicios systemctl stop php54-php-fpm systemctl stop php55-php-fpm systemctl stop php56-php-fpm systemctl stop php70-php-fpm systemctl stop php71-php-fpm systemctl stop php72-php-fpm systemctl stop php73-php-fpm #A cada version de PHP-FPM le asignamos un #puerto diferente mediante los siguientes comandos sed -i 's/:9000/:9054/' /opt/remi/php54/root/etc/php-fpm.d/www.conf sed -i 's/:9000/:9055/' /opt/remi/php55/root/etc/php-fpm.d/www.conf sed -i 's/:9000/:9056/' /etc/opt/remi/php56/php-fpm.d/www.conf sed -i 's/:9000/:9070/' /etc/opt/remi/php70/php-fpm.d/www.conf sed -i 's/:9000/:9071/' /etc/opt/remi/php71/php-fpm.d/www.conf sed -i 's/:9000/:9072/' /etc/opt/remi/php72/php-fpm.d/www.conf sed -i 's/:9000/:9073/' /etc/opt/remi/php73/php-fpm.d/www.conf #Cambimos el usuario, nginx en lugar de apache sed -i 's/user = apache/user = nginx/' /opt/remi/php54/root/etc/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /opt/remi/php54/root/etc/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /opt/remi/php55/root/etc/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /opt/remi/php55/root/etc/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /etc/opt/remi/php56/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /etc/opt/remi/php56/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /etc/opt/remi/php70/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /etc/opt/remi/php70/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /etc/opt/remi/php71/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /etc/opt/remi/php71/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /etc/opt/remi/php72/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /etc/opt/remi/php72/php-fpm.d/www.conf sed -i 's/user = apache/user = nginx/' /etc/opt/remi/php73/php-fpm.d/www.conf sed -i 's/group = apache/group = nginx/' /etc/opt/remi/php73/php-fpm.d/www.conf #Iniciamos los servicios systemctl start php56-php-fpm systemctl start php55-php-fpm systemctl start php56-php-fpm systemctl start php70-php-fpm systemctl start php71-php-fpm systemctl start php72-php-fpm systemctl start php73-php-fpm #Los iniciamos systemctl start nginx systemctl start mariadb #Configuramos para que todos arranque #desde el inicio de la ejecucion #del contenedor systemctl enable nginx systemctl enable mariadb systemctl enable php54-php-fpm systemctl enable php55-php-fpm systemctl enable php56-php-fpm systemctl enable php70-php-fpm systemctl enable php71-php-fpm systemctl enable php72-php-fpm systemctl enable php73-php-fpm #Opcional: Por ultimo en mi caso instalo composer yum install -y composer
Seleccionado una version de PHP
Cuando configuremos un nuevo dominio en Nginx para cambiar la versión de PHP solo debemos colocar alguna de las siguientes lineas:
#PHP 5.4 fastcgi_pass 127.0.0.1:9054; #PHP 5.5 fastcgi_pass 127.0.0.1:9055; #PHP 5.6 fastcgi_pass 127.0.0.1:9056; #PHP 7.0 fastcgi_pass 127.0.0.1:9070; #PHP 7.1 fastcgi_pass 127.0.0.1:9071; #PHP 7.2 fastcgi_pass 127.0.0.1:9072; #PHP 7.3 fastcgi_pass 127.0.0.1:9073;
Configuración de ejemplo por defecto para un sitio en Nginx
A modo de ejemplo guardamos un archivo de configuración con PHP 5.6 pre configurado, luego al momento de dar de alta un nuevo dominio lo tomaremos como ejemplo.
cat > /etc/nginx/conf.d/example.lan.conf << EOF server { listen 80; listen [::]:80; server_name example.lan; root /var/www/example.lan; index index.php index.html index.htm index.nginx-debian.html; location / { try_files \$uri \$uri/ =404; } location ~ \.php$ { try_files \$uri =404; #PHP 5.4 #fastcgi_pass 127.0.0.1:9054; #PHP 5.5 #fastcgi_pass 127.0.0.1:9055; #PHP 5.6 fastcgi_pass 127.0.0.1:9056; #PHP 7.0 #fastcgi_pass 127.0.0.1:9070; #PHP 7.1 #fastcgi_pass 127.0.0.1:9071; #PHP 7.2 #fastcgi_pass 127.0.0.1:9072; #PHP 7.3 #fastcgi_pass 127.0.0.1:9073; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; include fastcgi_params; fastcgi_buffer_size 128k; fastcgi_buffers 256 4k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; #php.ini fastcgi_param PHP_VALUE " memory_limit=512M; upload_max_filesize=5M; error_reporting=E_ALL; "; } location ~ /\.ht { deny all; } } EOF
Convertimos el Contenedor en Imagen
alvaro@acer:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bb0b488138bc centos-base "/usr/sbin/init" 11 minutes ago Exited (130) 2 seconds ago PasoDos e60ca0603d26 centos:latest "/bin/bash" 2 minutes ago Exited (0) 20 minutes ago PasoUno #Convertimos el contenedor llammado PasoDos en Imagen llamandolo por ejemplo nginx-multiphp alvaro@acer:~$ docker commit bb0b488138bc nginx-multiphp sha256:1c745640f601924fc21df4c80fdad19bb93f67fcb4cca80ad2c1d4264da11966
Limpiamos los contenedores que ya no necesitamos
#Borramos el contenedor PasoUno alvaro@acer:~$ docker rm PasoUno PasoUno #Borramos el contenedor PasoDos alvaro@acer:~$ docker rm PasoDos PasoDos
<
h3 style=”text-align: left;”>Revisamos las imágenes
En este punto nos quedaron 2 imagenes, un CentOS 7 recién instalado y uno con Nginx + MultiPHP y MySQL,la imagen llamada centos-base podemos borrarla si queremos, yo prefiero dejarla porque me sirve para otros propósitos, en ella ya esta solucionado el tema de reiniciar servicios.
alvaro@acer:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx-multiphp latest 1c745640f601 3 minutes ago 1.07GB centos-base latest 6d3b3ee2b754 18 minutes ago 333MB
Si quisiéramos borrar simplemente escribimos docker rmi centos-base
Trabajando con el nuevo contenedor
Ya tenemos listas la imagen que necesitamos, ahora creamos un nuevo contenedorcon el siguente comando, al contenedor lo voy a llamar MultiPHP y lo voy a constuir apartir de la imagen nginx-multiphp
docker run -it --privileged --hostname="server" -e "container=docker" --cap-add SYS_ADMIN \ --tmpfs /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -p 22:22 -p 80:80 -p 3306:3306 \ -v '/home/alvaro/www/:/var/www' \ --name MultiPHP "nginx-multiphp" "/usr/sbin/init"
Si ustedes colocaron un nombre diferente al momento de crear la imagen deberán colocar ese nombre, luego deberán modificar la linea -v ‘/home/alvaro/www/:/var/www’ y cambiar por la ruta que a ustedes les sirva, la primera ruta es la ubicacion de la carepta en nuestro disco duro, la segunda es en donde la vamos a montar dentro del contenedor.
Cuando lo corran aparecerá lo siguiente, recuerden que el usuario es root y la contraseña es docker o la que ustedes le hayan configurado
[ OK ] Reached target Network is Online. [ OK ] Started OpenSSH server daemon. [ OK ] Started The nginx HTTP and reverse proxy server. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started The PHP FastCGI Process Manager. [ OK ] Started MariaDB database server. [ OK ] Reached target Multi-User System. Starting Update UTMP about System Runlevel Changes... [ OK ] Started Update UTMP about System Runlevel Changes. CentOS Linux 7 (Core) Kernel 4.9.0-8-amd64 on an x86_64 server login:
Dando de alta un nuevo dominio
Para dar de alta un nuevo dominio hacemos
cp /etc/nginx/conf.d/example.lan.conf /etc/nginx/conf.d/ejemplo.com.conf nano /etc/nginx/conf.d/ejemplo.com.conf
Dentro del fichero cambiamos las lineas
server_name example.lan; root /var/www/example.lan;
Y las dejamos como
server_name ejemplo.com; root /var/www/ejemplo.com;
Guardamos y salimos del fichero y creamos la ruta
mkdir /var/www/ejemplo.com;
mkdir /var/www/ejemplo.com;
Reiniciamos Nginx
service nginx restart
Ejecutamos
echo "<?php phoinfo(); ?>;" > /var/www/ejemplo.com/index.php
Luego si modificamos el archivo host de nuestra pc apuntando a 127.0.0.1 podremos probar que la pagina funcione
127.0.0.1 ejemplo.com
Cambiando la versión de PHP
Para cambiar la version de PHP de un dominio modificamos
nano /etc/nginx/conf.d/ejemplo.com.conf
Vamos a la parte que aparece las versiones de PHP y descomentamos la version que nos interese y comentamos la que no.
#PHP 5.4 #fastcgi_pass 127.0.0.1:9054; #PHP 5.5 #fastcgi_pass 127.0.0.1:9055; #PHP 5.6 fastcgi_pass 127.0.0.1:9056; #PHP 7.0 #fastcgi_pass 127.0.0.1:9070; #PHP 7.1 #fastcgi_pass 127.0.0.1:9071; #PHP 7.2 #fastcgi_pass 127.0.0.1:9072; #PHP 7.3 #fastcgi_pass 127.0.0.1:9073;
Guardamos salimos y reinciamos Nginx
service nginx restart
Saliendo e ingresando nuevamente
De los contenedores CentOS normalmente salimos con exit porque usualmente ejecutan bash pero aquí estamos ejecutando init, por eso el comando para terminar el contenedor es halt
Un error muy comun al usar docker es cada vez que lo iniciamos hacerlo con docker run, esto nos comera el espacio en el disco duro porque estara creando un conenedor nuevo en lugar de usar el auq ya tengamos, la mejor manera de trabajar es con
docker start MultiPHP && docker attach MultiPHP
Administrador de Sistemas, Programador, Docente y ahora resulta que también Blogger (peor es ser tictoker). Más de 20 años de experiencia en computación atendiendo nabos y resolviendo problemas que sino fuera por estos nabos no habrían ocurrido en primer lugar. Escribo más que nada sobre tecnología y herramientas en general además de algunos artículos con opiniones tan subjetivas como irrelevantes, así que si no te gustan mejor madura.
Gracias por compartir, en mi caso no me funcionó, en el paso 2 me reinicia el pc, uso centos 7
Hola Alejando
Si se te reinicia la PC es porque alguno de los comandos no lo estas ejecutando dentro de docker sino tu PC, ten cuidado que no hayas hecho cambios en tu propio sistema operativo y no en el docker, desde tu PC solo arrancas docker y luego la instalación y configuración la haces dentro del contenedor, no fuera
Quizás te resulte mas sencillo este tutorial donde la imagen ya configurada, solo es descargar la imagen
https://www.alvarodeleon.net/centos7-nginx-multiphp/
Saludos