Dockerizando Laravel con Nginx MySQL y Docker Compose en Ubuntu 18.04 LTS
Laravel es un framework PHP gratuito y de código abierto que implementa el patrón de diseño MVC (Modelo-Vista-Controlador). Está diseñado con facilidad de uso y permite a los desarrolladores crear aplicaciones tanto simples como complejas en poco tiempo. Laravel fue creado por Taylor Otwell en 2011, como un intento de proporcionar una alternativa avanzada al framework CodeIgniter (CI). En 2011, Laravel lanzó la versión 1 y la versión 2, y la última versión 5.6 viene con más y mejores características como el soporte de la línea de comandos (CLI) llamado ‘artisan’, soporte para diferentes sistemas de bases de datos, mejoras en Route, etc.
En esta guía, vamos a mostrarte cómo Dockerizar el proyecto Laravel con PHP-FPM, la base de datos MySQL y el servidor web Nginx utilizando el Docker Compose en el servidor Ubuntu 18.04. Vamos a crear una nueva imagen docker para el proyecto Laravel, y luego crearemos el script docker-compose.yml que contiene algunos servicios incluyendo, la propia App/Laravel, el servidor web Nginx, y la base de datos MySQL.
Requisitos previos
- Ubuntu 18.04
- Privilegios de root
Qué vamos a hacer
- Instalar Docker y Docker Compose
- Descargar Laravel e instalar las dependencias
- Dockerizar el proyecto Laravel
- Definir el servicio de la aplicación Laravel
- Definir el servicio HTTP de Nginx
- Definir el servicio de base de datos MySQL
- Crear un host virtual Nginx para Laravel
- Crear un archivo Docker para la aplicación Laravel
- Construir el proyecto Laravel
- Post-Instalación de Laravel
Paso 1 – Instalar Docker y Docker Compose
En primer lugar, vamos a instalar los paquetes Docker y Docker Compose en el sistema Ubuntu. Y vamos a utilizar los paquetes Docker del repositorio oficial de Ubuntu.
Antes de seguir adelante, tenemos que actualizar los repositorios en el sistema Ubuntu. Simplemente ejecutando el siguiente comando.
sudo apt update
Ahora instala los paquetes Docker y Docker Compose utilizando el comando apt que aparece a continuación.
sudo apt install docker.io -y
sudo apt install docker-compose -y
Los paquetes Docker y Docker Compose deberían estar ahora instalados en el sistema, compruébalo utilizando los siguientes comandos.
docker version
docker-compose version
Como resultado, obtendrás la versión de Docker y Docker Compose en el sistema.
A continuación, tenemos que asignar el usuario no root al grupo docker para poder ejecutar el contenedor Docker para usuarios no root.
Para este caso, vamos a añadir el usuario llamado ‘hakase’ al grupo docker ejecutando el siguiente comando.
usermod -a -G docker hakase
Y después, entra en el shell del usuario ‘hakase’ y ejecuta el comando docker ‘hello-world’.
su - hakase
docker run hello-world
Ahora aparecerá el mensaje ‘Hello World’ de Docker, y la instalación de Docker se habrá completado.
Paso 2 – Descargar Laravel e instalar las dependencias
En este paso, vamos a descargar el marco web Laravel en el directorio de inicio ‘hakase’ y luego instalaremos las dependencias de Laravel utilizando la imagen docker PHP ‘composer’. Para ello, asegúrate de que has iniciado sesión en el servidor como usuario no root.
Descarga el proyecto Laravel en el directorio ‘myapp’ y entra en él.
git clone https://github.com/laravel/laravel.git myapp/
cd myapp/
Ahora ejecuta el siguiente comando docker para instalar las dependencias de Laravel.
docker run --rm -v $(pwd):/app composer install
Con el comando anterior, vamos a ejecutar un nuevo contenedor docker temporal y montar el directorio del proyecto ‘myapp’ en el directorio ‘/app’ del contenedor. El contenedor se basa en la imagen docker ‘composer’, y vamos a instalar las dependencias de Laravel utilizando el comando ‘composer’ dentro de ese contenedor temporal.
Una vez terminada la instalación de las dependencias de Laravel, debemos cambiar el propietario del directorio ‘myapp’ por nuestro propio usuario utilizando el comando sudo que aparece a continuación.
sudo chown -R $USER:$USER ~/myapp
Paso 3 – Dockerizar el proyecto Laravel
Después de descargar Laravel e instalar sus dependencias, vamos a crear un nuevo script docker-compose.yml y crear un nuevo Dockerfile para el proyecto Laravel.
cd myapp/
vim docker-compose.yml
– Definir el servicio de la aplicación Laravel
En primer lugar, vamos a definir el propio proyecto Laravel y a construir la imagen docker para el proyecto Laravel utilizando el Dockerfile.
Pega en él el script docker compose.
version: '3'
services:
#Laravel App
app:
build:
context: .
dockerfile: Dockerfile
image: hakase-labs/laravel
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www/html
volumes:
- ./:/var/www/html
networks:
- mynet
Detalles del servicio de contenedores de Laravel:
- El servicio de contenedores Laravel se llamará ‘app’. Se basa en nuestra imagen docker personalizada que se creará con nuestro ‘Dockerfile’, y la nueva imagen se llamará ‘hakase-labs/laravel’.
- Queremos montar el directorio del proyecto ‘myapp’ en ‘/var/www/html’ dentro del servicio de contenedores.
- Vamos a utilizar la red docker personalizada para nuestra configuración, la red se llamará ‘mynet’.
– Definir el servicio HTTP de Nginx
Ahora definiremos el servicio de contenedor nginx.
Pega la siguiente configuración después de la línea del servicio de contenedor ‘app’.
#Nginx Service
nginx:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www/html
- ./nginx/conf.d/:/etc/nginx/conf.d/
- ./nginx/ssl/:/etc/nginx/ssl/
networks:
- mynet
Detalles de la configuración del servicio de contenedores nginx:
- Queremos crear un nuevo contenedor llamado ‘nginx’ basado en la imagen docker ‘nginx:alpine’.
- El servicio contenedor abrirá los puertos HTTP y HTTPS.
- El contenedor montará tres volúmenes diferentes. El directorio del proyecto ‘myapp’ en el directorio ‘/var/www/html’, la configuración del host virtual nginx ‘nginx/conf.d/’ en el directorio ‘/etc/nginx/conf.d’, y montará los archivos del certificado ‘nginx/ssl/’ en el directorio ‘/etc/nginx/ssl’ del contenedor.
- El servicio del contenedor utilizará la misma red llamada ‘mynet’.
– Definir el servicio de base de datos MySQL
Y por último, definimos el servicio de base de datos MySQL.
Pega la siguiente configuración después de la línea del servicio del contenedor ‘nginx’.
#MySQL Service
db:
image: mysql:5.7
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laraveldb
MYSQL_USER: laravel
MYSQL_PASSWORD: laravelpassworddb
MYSQL_ROOT_PASSWORD: rootpasswordmysql
volumes:
- mysqldata:/var/lib/mysql/
networks:
- mynet
#Docker Networks
networks:
mynet:
driver: bridge
#Volumes
volumes:
mysqldata:
driver: local
Guarda y cierra la configuración.
Detalla el servicio contenedor MySQL:
- El servicio contenedor de MySQL se llamará ‘db’, basándose en la imagen docker ‘mysql:5.7’.
- El servicio ‘db’ abrirá el puerto por defecto de MySQL ‘3306’.
- El proyecto Laravel utilizará la base de datos, el usuario y la contraseña basados en la variable de entorno del servicio ‘db’.
- El servicio ‘db’ de MySQL montará el volumen llamado ‘mysqldata’, y tendrá la misma red ‘mynet’.
- Y definimos la red personalizada ‘mynet’ con el controlador ‘bridge’, y el volumen ‘mysqldata’ utilizará el controlador ‘local’.
A continuación se muestra la configuración completa de ‘docker-compose.yml’:
version: '3' services: #Laravel App app: build: context: . dockerfile: Dockerfile image: hakase-labs/laravel container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www/html volumes: - ./:/var/www/html networks: - mynet #Nginx Service nginx: image: nginx:alpine container_name: nginx restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www/html - ./nginx/conf.d/:/etc/nginx/conf.d/ - ./nginx/ssl/:/etc/nginx/ssl/ networks: - mynet #MySQL Service db: image: mysql:5.7 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laraveldb MYSQL_USER: laravel MYSQL_PASSWORD: laravelpassworddb MYSQL_ROOT_PASSWORD: rootpasswordmysql volumes: - mysqldata:/var/lib/mysql/ networks: - mynet #Docker Networks networks: mynet: driver: bridge #Volumes volumes: mysqldata: driver: local
– Crea un host virtual Nginx para Laravel
Dentro del directorio del proyecto ‘myapp’, crea un nuevo directorio llamado ‘nginx’ que contendrá otros dos directorios ‘conf.d’ y ‘ssl’. A continuación, crea una nueva configuración de host virtual nginx ‘laravel.conf’ dentro del directorio ‘conf.d’.
Ejecuta el siguiente comando.
mkdir -p nginx/{conf.d,ssl}
vim nginx/conf.d/laravel.conf
server { listen 80; server_name laravel.hakase-labs.io; return 301 https://laravel.hakase-labs.io$request_uri; } server { listen 443 ssl http2; server_name laravel.hakase-labs.io; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; # Log files for Debug error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; # Laravel web root directory root /var/www/html/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } # Nginx Pass requests to PHP-FPM location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }
Guarda y cierra.
Después, copia tu archivo de certificado ssl en el directorio ‘nginx/ssl/’.
sudo cp /path/to/ssl/fullchain.pem nginx/ssl/
sudo cp /path/to/ssl/privkey.pem nginx/ssl/
– Crea un Dockerfile para la aplicación Laravel
A continuación, crea un nuevo Dockerfile para el proyecto Laravel.
Ejecuta el siguiente comando.
vim Dockerfile
Pega la configuración de abajo.
# Set master image FROM php:7.2-fpm-alpine # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/html/ # Set working directory WORKDIR /var/www/html # Install Additional dependencies RUN apk update && apk add --no-cache \ build-base shadow vim curl \ php7 \ php7-fpm \ php7-common \ php7-pdo \ php7-pdo_mysql \ php7-mysqli \ php7-mcrypt \ php7-mbstring \ php7-xml \ php7-openssl \ php7-json \ php7-phar \ php7-zip \ php7-gd \ php7-dom \ php7-session \ php7-zlib # Add and Enable PHP-PDO Extenstions RUN docker-php-ext-install pdo pdo_mysql RUN docker-php-ext-enable pdo_mysql # Install PHP Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Remove Cache RUN rm -rf /var/cache/apk/* # Add UID '1000' to www-data RUN usermod -u 1000 www-data # Copy existing application directory permissions COPY --chown=www-data:www-data . /var/www/html # Change current user to www USER www-data # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]
Guarda y cierra la configuración.
Y ya estamos listos para construir el proyecto Laravel ‘myapp’ y ejecutar los servicios del contenedor que hemos definido.
Paso 4 – Construir Laravel con los servicios Nginx y MySQL
Construye la imagen docker personalizada para nuestro proyecto Laravel utilizando el siguiente comando.
docker-compose build
A continuación, ejecuta de nuevo el siguiente comando.
docker-compose up -d
Descargará todas las imágenes docker que necesitemos y luego construirá los servicios de contenedor basándose en la configuración ‘docker-compose.yml’.
Cuando se haya completado, verifícalo utilizando el comando docker-compose que aparece a continuación.
docker-compose ps
Y como resultado, obtendrás que los tres servicios de contenedor están en marcha. La ‘app’ que se ejecuta en el puerto por defecto ‘9000’ PHP-FPM, el servicio ‘nginx’ está en los puertos HTTP y HTTPS, y el servicio ‘db’ MySQL en el puerto por defecto MySQL ‘3306’.
Después de esto, verifica de nuevo todas las imágenes docker disponibles y los puertos abiertos en el sistema.
docker-compose images
netstat -plntu
Tendrás la imagen docker personalizada ‘hakase-labs/laravel’ en la lista, y los puertos HTTP y HTTPS están en estado ‘LISTEN’.
Paso 5 – Post-Instalación de Laravel
Hasta esta etapa, el proyecto Laravel está funcionando como un contenedor Docker. Y ahora vamos a crear un nuevo archivo ‘.env’, generar la clave y migrar los datos de Laravel utilizando la línea de comandos de Laravel ‘artisan’.
Copia el ejemplo de archivo ‘.env’ y edítalo dentro del contenedor.
cp .env.example .env
docker-compose exec app vim .env
Cambia la configuración de la base de datos como se indica a continuación.
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=laravel
DB_PASSWORD=laravelpassworddb
Guarda y cierra.
A continuación, genera la clave de la aplicación Laravel y borra la configuración de la caché.
docker-compose exec app php artisan key:generate
docker-compose exec app php artisan config:cache
Después, migra la base de datos con el siguiente comando.
docker-compose exec app php artisan migrate
Asegúrate de que no hay ningún error.
Ahora abre tu navegador web y escribe el nombre de dominio de tu proyecto
http://laravel.hakase-labs.io/
Y serás redirigido a la conexión segura HTTPS y se mostrará la página de inicio de Laravel por defecto como se muestra a continuación.
Finalmente, la Dockerización del proyecto Laravel con el servidor web Nginx y la base de datos MySQL se ha completado con éxito.