9

Docker para Laravel + MySQL

Adrian
adranuz
26319

adranuz/php-env-docker

Hace mucho tiempo… quise aprender Docker para poder correr proyectos en mi PC sin tener que andar moviendo la versión de PHP y MySQL y todo ese infierno que conoce la gente que trabaja en varios proyectos de diferentes versiones y todo eso 😥. Y que crees, aprendí la sintaxis de Docker, pero nunca pude construir nada o copiar algún entorno para poder hacerlo, así que use Laragon, XAMP o Hombrew para mis entornos.

Hoy que tengo un proyecto con Laravel y MySQL, me di una n oportunidad para crear el entorno, y con ayuda de internet y mi previo conocimiento sobre Docker pude generar uno 😜, y digo generar porque ninguno de los que encontré en internet me funciono, pero si tuve que basarme en ellos para hacer uno que me funcione a mí, principalmente en este Link.

¡Si deseas correr tu app PHP ya! Puedes acceder a mi repo y seguir los pasos descritos en el readme.md del repositorio.

Necesitas antes

Antes que nada necesitas instalar Docker, y ese es un viaje algo largo si es tu primera vez. No te preocupes, solo debes de leer bien las instrucciones oficiales, y por ahí debe haber tutoriales de como hacerlo. Yo creo en ti. Busca por todos lados hasta que lo consigas.

¿Ya tenemos Docker? ¡A pensar!

Describiendo la arquitectura

Así tengo la estructura de mis documentos, y espero que me la copies, porque por supuesto, yo la copie de alguien más 👀: Link.

// Estructura
> mysql                // carpeta de configuracion de mysql
> nginx/default.conf// archivo de configuracion nginx
> src                  // proyecto php
.gitignore// si es que necesitas uno
docker-compose.yml// declaracion de los servicios
Dockerfile             // declaracion del servicio principal

Descripción gráfica:

Untitled (16).png

Describiendo docker-compose.yml

Espero no te molesten los comments inline, porque suelo hacerlos un montón.

Te presento el docker-compose.yml.

version:"3.7"# version del docker-compose(?)services:  nginx:# 1er servicio: nginx    image: nginx:stable-alpine # imagen de docker hub que vamos a usar    container_name: nginx # nombre para referirse al servicio    ports:      -8000:80# puerto de mi pc:puerto del servicio    volumes:      - ./src:/var/www/html # carpeta local/ vincula a carpeta de nginx      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # archivo local / reflejado en archivo de la imagen    depends_on:# para correr este servicio debe estar corriendo php y mysql antes      - php
      - mysql
    networks:# la red que los conecta se llama laravel      - laravel

  mysql:# 2do servici    image: mysql:5.7# imagen de docker hub    container_name: mysql # nombre de referencia del servicio    restart: unless-stopped # si tiene algun problema, reinicialo    tty:true# aqui si le fallo joven xD, 👀 leo los comentarios    ports:      -33069:3306# puerto local:puerto del servicio    volumes:      - ./mysql:/var/lib/mysql # carpeta local:carpeta de config de mysql    environment:# datos de configuracion del entorno      MYSQL_DATABASE:'homestead'# importante que tengan comillas      MYSQL_USER:'homestead'      MYSQL_PASSWORD:'secret'      MYSQL_ROOT_PASSWORD:'secret.root'      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    networks:      - laravel # red  php:# 3er servicio    build:# este se construira aqui mismo      context: . # ruta de referencia ./      dockerfile: Dockerfile # nombre del archivo de configuracion de la imagen     container_name: php #    volumes:# carpeta de proyecto local : carpeta del container que da vida a los archivos PHP      - ./src:/var/www/html 
    ports:      -9000:80# ya te la sabes 😉    networks:      - laravel # rednetworks:# declaracion de la red  laravel:

Resumen: Instalamos y configuramos las imágenes que ya existen en DockerHub de MySQL y Nginx, y declaramos que al 3er servicio será cargado a partir de otro archivo de configuración llamado Dockerfile, pero tambien agregamos algunas configuraciones.

PD: El repositorio contiene todos los archivos sin comentarios.

Describiendo Dockerfile

Dockerfile es un archivo muy parecido al anterior, pero se usa en contenedores individuales(?). Este archivo fue construido mediante documentación y stackoverflow 🦚, cada fallo.

# imagen de dockerhub que descargaraFROM php:7.3-fpm-alpine

# algunas configuraciones para que funcione el contenedorRUNdocker-php-ext-install pdo pdo_mysql
# instala composer en el contenedorRUNcurl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# da permisos para editar los archivos en esta ruta del containerRUNchown -R www-data:www-data /var/www
RUNchmod 755 /var/www

Archivos de configuración

Por suerte solo hay 1: nginx. Todo lo demás ya fue configurado en Docker. Tengo que confesar que es la primera vez que trabajo con Nginx, toda la configuración fue un copypaste del primer tutorial que vi, pero dejo los comentarios por mera interpretación.

PD: Solicito apoyo 6.6

# configuracion del servidor de nginx
server {
  listen80; # puerto del container
  index index.php index.html; # busca interpretar archivos de este tpo
  server_name localhost; # usa el localhost
  error_log /var/log/nginx/error.log; # registros de errores
  access_log /var/log/nginx/access.log; # registros de acceso
  root /var/www/html/public; # usara esta ruta como la root# a partir de aqui todo es muy confuso 😹
  location~ \.php$ {  
    try_files$uri =404; # por defecto regresa el 404
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000; # puerto al que se conectara para obtener sus archivos
    fastcgi_index index.php; # el archivo raiz por defaultinclude fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
  }

  location / {
    try_files$uri/ $uri /index.php?$query_string;
    gzip_staticon;
  }

}

Y tengo un archivo .gitignore por si quiero subir esto al Github

src/* # para que se lleve el contenido de src, dejandome la carpeta src
mysql/* # que se lleve todo el contenido de mysql excepto la misma carpeta

Corriendo el proyecto

Corre el entorno:

$ docker-compose build # trae y configura las imagenes$ docker-compose up -d # enciende los containers y la red

Abre tu Docker y verás que tus servicios ya están corriendo 🤞.

A mí me dio un pequeño problema al correrlo la primera vez, pero funciono al dar el comando $ docker-compose down y después $ docker-compose up.

Untitled (17).png

Agregando un proyecto con PHP

A partir de aquí es prácticamente es lo mismo que tengo en el repositorio.

  1. Mueve a la carpeta src.

    $ cd src
    
    
  2. Clona tu proyecto en src.

    # Es importante el espacio yel punto al final, porque así se instalara enla carpeta enla queestá situado. 
    # En este caso el proyecto que agregue es el default de Laravel.
    $ git clone https://github.com/laravel/laravel.git .
  3. Instala las dependencias de composer mediante Docker.

    # de esta manera puedes 
    $ docker-compose exec php composer install --ignore-platform-reqs
    
    
  4. Copia y renombra el archivo .env.example => .env.

  5. Agrega el app key.

    $ docker-compose exec php php artisan key:generate
    
    
  6. Abre el navegador en el puerto declarado en el docker-compose.yml para Nginx. En este caso es el puerto 8888. Si ves algo, lo que sea, hasta un error, ya estamos del otro lado.

Conectando la base de datos

En el archivo docker-compose.yml vienen declaradas las configuraciones de la db, las puedes cambiar si gustas. Las que deje por default son:

ports: 
  - 33069:3306container_name: mysql
environment:
  MYSQL_DATABASE: 'homestead'MYSQL_USER: 'homestead'MYSQL_PASSWORD: 'secret'MYSQL_ROOT_PASSWORD: 'secret.root'

Conecta el container con tu manejador de base de datos. En mi caso es Workbench. Como vez agrego los datos de user root, pero puedes agregar el usuario normal que tiene poder sobre la DB declarada en el docker-compose.yml.

Untitled (18).png

Después de esto deberás importar tu base de datos. Hay muchas formas de hacerlo dependiendo de tu gestor o si usas la terminal. Yo use Workbench, pero si tienes otro te doy una pista: “Como importar un archivo a mi base de datos con Workbench” en Google.

Ahora conecta tu proyecto con la base de datos. Esto lo logre abriendo el archivo .env e ingresando los datos del puerto local del servicio mysql.

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=secret.root

¿Listo para que todo arda? Haremos la migración.

Una migración exitosa confirmaría que la conexión con la base de datos es correcta, pero antes de hacerla limpiaremos el caché.

$ docker-compose exec php php artisan config:clear
$ docker-compose exec php php artisan cache:clear
$ docker-compose exec php php artisan view:clear
$ docker-compose exec php php artisan config:cache

Ojo: si te sale algún error es porque no tienes permisos root en las carpetas de tu proyecto o que no existen las carpetas de caché, para esto tengo 2 comandos para ti.

# para obtener permisos dentro del servicio php
$ docker-compose exec php chown -R www-data: /var/www/html

# para crear las carpetas del proyecto de php desde la carpeta src
$ pwd# debe decir que estas enla carpeta src
$ mkdir storage/framework/{views, testing, sessions, cache/data}

#puede que sea diferente para proyectos queno sean Laravel, ahi se los dejo a ustedes y su superpoder Google.

Ahora si: migración.

$ docker-compose exec php php artisan migrate

Si tuviste una migración exitosa, felicidades.

Con todo este desarrollo ya deberías poder acceder a la ruta principal o a algunas de tus rutas declaradas en tu carpeta routes.

¡Si no, felicidades también! ¡Ya tienes casi todo funcionando! Los servidores, la base de datos, solo es solucionar eso que no te permite conectar tu DB con el proyecto. Mi sugerencia: consulta a tus conocidos, escribe preguntas, lee doc, usa stackoverflow. Te entiendo completamente, la creación de entornos con PHP es mucho trabajo, pero siempre hay una manera (? I hope so).

Extra

Mi proyecto tenía la dependencia de passport, por lo que para poder trabajar debería de crear credenciales.

$ docker-compose exec php php artisan passport:install

Para esto las generé y las agregué en mi archivo app/Http/Controllers/Users/User.php

// ...
// line 53
			$request->request->add([
            'scope' => $scope,
            'grant_type' => 'password',
            'client_id' => '20',
            'client_secret' => 'x5iM00tRbKcNFFXV7sz7psJjjIP3e1iHTawjR8iu',
            'username' => Input::get($type),
            'type_username' => $type
        ]);
        return Route::dispatch(
            Request::create('/api/oauth/token', 'post')
        );
// ...

Y los comandos de PHP artisan y composer???

Para acceder a la terminal de cada servicio puedes hacerlo de dos formas:

  • Por medio de la interfaz de Docker abriendo la terminal del servicio:
    Untitled (19).png

  • Mediante comandos de docker-compose que mandan a ejecutar una linea en un servicio (como lo hice en todo el tuto).

    # docker-compose ejecuta servicio-php 
    $ docker-compose exec php php artisan migrate
    

Por fin

Recuerda que para

¡Felicidades! Acabas de consultar otra fuente, espero que sea la que te funcione. Si no, recuerda: Divide el problema y ¡No pares de buscar la solución!

Escribe tu comentario
+ 2