Compartir comentarios
Las respuestas se generan en base a la documentación.

Usar contenedores para el desarrollo de PHP

Requisitos previos

Completa Contenedorizar una aplicación PHP.

Descripción general

En esta sección, aprenderás cómo configurar un entorno de desarrollo para tu aplicación contenedorizada. Esto incluye:

  • Agregar una base de datos local y persistir datos
  • Agregar phpMyAdmin para interactuar con la base de datos
  • Configurar Compose para actualizar automáticamente tus servicios de Compose en ejecución a medida que editas y guardas tu código
  • Crear un contenedor de desarrollo que contenga las dependencias de desarrollo

Agregar una base de datos local y persistir datos

Puedes usar contenedores para configurar servicios locales, como una base de datos. Para hacer esto en la aplicación de ejemplo, deberás hacer lo siguiente:

  • Actualizar el Dockerfile para instalar extensiones para conectarse a la base de datos
  • Actualizar el archivo compose.yaml para agregar un servicio de base de datos y un volumen para persistir datos

Actualizar el Dockerfile para instalar extensiones

Para instalar extensiones de PHP, necesitas actualizar el Dockerfile. Abre tu Dockerfile en un IDE o editor de texto y luego actualiza su contenido. El siguiente Dockerfile incluye una nueva línea que instala las extensiones pdo y pdo_mysql. Se han eliminado todos los comentarios.

# syntax=docker/dockerfile:1

FROM composer:lts as deps
WORKDIR /app
RUN --mount=type=bind,source=composer.json,target=composer.json \
    --mount=type=bind,source=composer.lock,target=composer.lock \
    --mount=type=cache,target=/tmp/cache \
    composer install --no-dev --no-interaction

FROM php:8.2-apache as final
RUN docker-php-ext-install pdo pdo_mysql
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=deps app/vendor/ /var/www/html/vendor
COPY ./src /var/www/html
USER www-data

Para obtener más detalles sobre la instalación de extensiones de PHP, consulta la Imagen oficial de Docker para PHP.

Actualizar el archivo compose.yaml para agregar una base de datos y persistir datos

Abre el archivo compose.yaml en un IDE o editor de texto. Notarás que ya contiene instrucciones comentadas para una base de datos PostgreSQL y un volumen. Para esta aplicación, utilizarás MariaDB. Para obtener más detalles sobre MariaDB, consulta la Imagen oficial de Docker para MariaDB.

Abre el archivo src/database.php en un IDE o editor de texto. Notarás que lee variables de entorno para conectarse a la base de datos.

En el archivo compose.yaml, deberás actualizar lo siguiente:

  1. Descomentar y actualizar las instrucciones de la base de datos para MariaDB.
  2. Agregar un secreto al servicio del servidor para pasar la contraseña de la base de datos.
  3. Agregar las variables de entorno de conexión a la base de datos al servicio del servidor.
  4. Descomentar las instrucciones del volumen para persistir datos.

El siguiente es el archivo compose.yaml actualizado. Se han eliminado todos los comentarios.

services:
  server:
    build:
      context: .
    ports:
      - 9000:80
    depends_on:
      db:
        condition: service_healthy
    secrets:
      - db-password
    environment:
      - PASSWORD_FILE_PATH=/run/secrets/db-password
      - DB_HOST=db
      - DB_NAME=example
      - DB_USER=root
  db:
    image: mariadb
    restart: always
    user: root
    secrets:
      - db-password
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
      - MARIADB_DATABASE=example
    expose:
      - 3306
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--su-mysql",
          "--connect",
          "--innodb_initialized",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
volumes:
  db-data:
secrets:
  db-password:
    file: db/password.txt
Note

Para obtener más información sobre las instrucciones en el archivo de Compose, consulta la referencia del archivo Compose.

Antes de ejecutar la aplicación usando Compose, ten en cuenta que este archivo de Compose utiliza secrets y especifica un archivo password.txt para contener la contraseña de la base de datos. Debes crear este archivo, ya que no está incluido en el repositorio de origen.

En el directorio docker-php-sample, crea un nuevo directorio llamado db y dentro de ese directorio crea un archivo llamado password.txt. Abre password.txt en un IDE o editor de texto y agrega la siguiente contraseña. La contraseña debe estar en una sola línea, sin líneas adicionales en el archivo.

example

Guarda y cierra el archivo password.txt.

Ahora deberías tener lo siguiente en tu directorio docker-php-sample.

├── docker-php-sample/
│ ├── .git/
│ ├── db/
│ │ └── password.txt
│ ├── src/
│ ├── tests/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── composer.json
│ ├── composer.lock
│ ├── Dockerfile
│ ├── README.Docker.md
│ └── README.md

Ejecuta el siguiente comando para iniciar tu aplicación.

$ docker compose up --build

Abre un navegador y visita la aplicación en http://localhost:9000/database.php. Deberías ver una aplicación web sencilla con texto y un contador que se incrementa cada vez que actualizas la página.

Presiona ctrl+c en la terminal para detener tu aplicación.

Verificar que los datos persisten en la base de datos

En la terminal, ejecuta docker compose rm para eliminar tus contenedores y luego ejecuta docker compose up para ejecutar tu aplicación nuevamente.

$ docker compose rm
$ docker compose up --build

Actualiza http://localhost:9000/database.php en tu navegador y verifica que el conteo anterior aún exista. Sin un volumen, los datos de la base de datos no persistirían después de eliminar el contenedor.

Presiona ctrl+c en la terminal para detener tu aplicación.

Agregar phpMyAdmin para interactuar con la base de datos

Puedes agregar servicios fácilmente a tu pila de aplicaciones actualizando el archivo compose.yaml.

Actualiza tu compose.yaml para agregar un nuevo servicio para phpMyAdmin. Para obtener más detalles, consulta la Imagen oficial de Docker para phpMyAdmin. El siguiente es el archivo compose.yaml actualizado.

services:
  server:
    build:
      context: .
    ports:
      - 9000:80
    depends_on:
      db:
        condition: service_healthy
    secrets:
      - db-password
    environment:
      - PASSWORD_FILE_PATH=/run/secrets/db-password
      - DB_HOST=db
      - DB_NAME=example
      - DB_USER=root
  db:
    image: mariadb
    restart: always
    user: root
    secrets:
      - db-password
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
      - MARIADB_DATABASE=example
    expose:
      - 3306
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--su-mysql",
          "--connect",
          "--innodb_initialized",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
  phpmyadmin:
    image: phpmyadmin
    ports:
      - 8080:80
    depends_on:
      - db
    environment:
      - PMA_HOST=db
volumes:
  db-data:
secrets:
  db-password:
    file: db/password.txt

En la terminal, ejecuta docker compose up para ejecutar tu aplicación nuevamente.

$ docker compose up --build

Abre http://localhost:8080 en tu navegador para acceder a phpMyAdmin. Inicia sesión usando root como nombre de usuario y example como contraseña. Ahora puedes interactuar con la base de datos a través de phpMyAdmin.

Presiona ctrl+c in the terminal to stop your application.

Actualizar servicios automáticamente

Usa Compose Watch para actualizar automáticamente tus servicios de Compose en ejecución a medida que editas y guardas tu código. Para obtener más detalles sobre Compose Watch, consulta Usar Compose Watch.

Abre tu archivo compose.yaml en un IDE o editor de texto y luego agrega las instrucciones de Compose Watch. El siguiente es el archivo compose.yaml actualizado.

services:
  server:
    build:
      context: .
    ports:
      - 9000:80
    depends_on:
      db:
        condition: service_healthy
    secrets:
      - db-password
    environment:
      - PASSWORD_FILE_PATH=/run/secrets/db-password
      - DB_HOST=db
      - DB_NAME=example
      - DB_USER=root
    develop:
      watch:
        - action: sync
          path: ./src
          target: /var/www/html
  db:
    image: mariadb
    restart: always
    user: root
    secrets:
      - db-password
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
      - MARIADB_DATABASE=example
    expose:
      - 3306
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--su-mysql",
          "--connect",
          "--innodb_initialized",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
  phpmyadmin:
    image: phpmyadmin
    ports:
      - 8080:80
    depends_on:
      - db
    environment:
      - PMA_HOST=db
volumes:
  db-data:
secrets:
  db-password:
    file: db/password.txt

Ejecuta el siguiente comando para ejecutar tu aplicación con Compose Watch.

$ docker compose watch

Abre un navegador y verifica que la aplicación se esté ejecutando en http://localhost:9000/hello.php.

Cualquier cambio en los archivos fuente de la aplicación en tu máquina local se reflejará inmediatamente en el contenedor en ejecución.

Abre hello.php en un IDE o editor de texto y actualiza la cadena Hello, world! a Hello, Docker!.

Guarda los cambios en hello.php y espera unos segundos para que la aplicación se sincronice. Actualiza http://localhost:9000/hello.php en tu navegador y verifica que aparezca el texto actualizado.

Presiona ctrl+c en la terminal para detener Compose Watch. Ejecuta docker compose down en la terminal para detener la aplicación.

Crear un contenedor de desarrollo

En este punto, cuando ejecutas tu aplicación contenedorizada, Composer no está instalando las dependencias de desarrollo. Si bien esta imagen pequeña es buena para producción, carece de las herramientas y dependencias que puedes necesitar al desarrollar y no incluye el directorio tests. Puedes utilizar construcciones multietapa para construir etapas tanto para desarrollo como para producción en el mismo Dockerfile. Para obtener más detalles, consulta Construcciones multietapa.

En el Dockerfile, deberás actualizar lo siguiente:

  1. Dividir la etapa deps en dos etapas. Una etapa para producción (prod-deps) y una etapa (dev-deps) para instalar dependencias de desarrollo.
  2. Crear una etapa base común.
  3. Crear una nueva etapa development para desarrollo.
  4. Actualizar la etapa final para copiar dependencias de la nueva etapa prod-deps.

El siguiente es el Dockerfile antes y después de los cambios.

# syntax=docker/dockerfile:1

FROM composer:lts as deps
WORKDIR /app
RUN --mount=type=bind,source=composer.json,target=composer.json \
    --mount=type=bind,source=composer.lock,target=composer.lock \
    --mount=type=cache,target=/tmp/cache \
    composer install --no-dev --no-interaction

FROM php:8.2-apache as final
RUN docker-php-ext-install pdo pdo_mysql
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=deps app/vendor/ /var/www/html/vendor
COPY ./src /var/www/html
USER www-data
# syntax=docker/dockerfile:1

FROM composer:lts as prod-deps
WORKDIR /app
RUN --mount=type=bind,source=./composer.json,target=composer.json \
    --mount=type=bind,source=./composer.lock,target=composer.lock \
    --mount=type=cache,target=/tmp/cache \
    composer install --no-dev --no-interaction

FROM composer:lts as dev-deps
WORKDIR /app
RUN --mount=type=bind,source=./composer.json,target=composer.json \
    --mount=type=bind,source=./composer.lock,target=composer.lock \
    --mount=type=cache,target=/tmp/cache \
    composer install --no-interaction

FROM php:8.2-apache as base
RUN docker-php-ext-install pdo pdo_mysql
COPY ./src /var/www/html

FROM base as development
COPY ./tests /var/www/html/tests
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
COPY --from=dev-deps app/vendor/ /var/www/html/vendor

FROM base as final
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=prod-deps app/vendor/ /var/www/html/vendor
USER www-data

Actualiza tu archivo compose.yaml agregando una instrucción para apuntar a la etapa de desarrollo.

La siguiente es la sección actualizada del archivo compose.yaml.

services:
  server:
    build:
      context: .
      target: development
      # ...

Tu aplicación contenedorizada ahora instalará las dependencias de desarrollo.

Ejecuta el siguiente comando para iniciar tu aplicación.

$ docker compose up --build

Abre un navegador y visita la aplicación en http://localhost:9000/hello.php. Deberías seguir ver la aplicación simple "Hello, Docker!".

Presiona ctrl+c en la terminal para detener tu aplicación.

Aunque la aplicación se vea igual, ahora puedes hacer uso de las dependencias de desarrollo. Continúa con la siguiente sección para aprender cómo puedes ejecutar pruebas usando Docker.

Resumen

En esta sección, revisamos cómo configurar tu archivo de Compose para agregar una base de datos local y persistir datos. También aprendiste cómo usar Compose Watch para sincronizar automáticamente tu aplicación al actualizar tu código. Y finalmente, aprendiste cómo crear un contenedor de desarrollo que contenga las dependencias necesarias para el desarrollo.

Información relacionada:

Pasos siguientes

En la siguiente sección, aprenderás cómo ejecutar pruebas unitarias usando Docker.