Cómo crear de forma segura una imagen Docker de una aplicación PHP
James Olaogun
2 de agosto de 2023
0 minutos de lecturaNota del editor: 10 de agosto de 2023
Esta publicación se actualizó para incluir una versión más reciente de PHP en el tutorial.
Supongamos que desarrollaste una aplicación PHP, pero quieres separarla de la infraestructura de soporte de forma que sea liviana, portátil y bastante segura. Quieres que otros desarrolladores puedan trabajar en ella sin tener que recrear entornos completos. En resumen, lo que quieres hacer es crear un contenedor para tu aplicación: empaquetarla junto con sus dependencias en contenedores que se puedan compartir fácilmente entre distintos entornos.
La solución de contenedores más popular hoy en día es Docker, una plataforma de código abierto que se presentó en 2013. Desde entonces, se ha convertido en una tecnología ampliamente adoptada en el desarrollo de software para aislar aplicaciones, crear componentes de CI/CD reutilizables y permitir una implementación rápida.
Este tutorial te muestra paso a paso cómo crear contenedores de forma segura para una aplicación PHP o, más específicamente, cómo «dockerizarla». También usarás Snyk, una plataforma de seguridad para desarrolladores que ofrece herramientas para proteger aplicaciones modernas, identificar vulnerabilidades y automatizar su corrección.
Requisitos previos y recomendaciones
Antes de comenzar el siguiente tutorial, tómate un momento para asegurarte de tener estas herramientas:
Docker instalado en tu equipo. Lo usarás para ejecutar y administrar el contenedor PHP.
Una cuenta gratuita de Snyk. Las herramientas de análisis de seguridad de Snyk detectarán y corregirán vulnerabilidades en los contenedores.
NPM o Yarn para instalar y ejecutar la Snyk CLI.
Una aplicación PHP básica. En este tutorial se usa un proyecto de Laravel recién creado.
Cuando tengas la seguridad de que cumples esos requisitos, considera los siguientes consejos antes de continuar con el tutorial. Estas recomendaciones te ayudarán a dockerizar tu aplicación PHP de forma sencilla y segura.
Usa una versión específica de la imagen para las compilaciones
Asegúrate siempre de usar una versión específica de la imagen Docker al compilar tu aplicación. Por ejemplo, en lugar de descargar PHP-FPM, puedes especificar la versión de la imagen y descargar PHP:8.0-fpm. Ten en cuenta que la imagen base que uses dependerá de los requisitos de versión de tu aplicación.
Así, puedes tener la certeza de que tu aplicación se compila sobre una versión conocida, probada y estable. Además, sabrás que la versión de la imagen puede usar la misma plataforma subyacente y las mismas dependencias en distintos entornos, lo que puede mejorar la reproducibilidad y la coherencia.
No uses ADD para dependencias remotas
El comando ADD puede descargar archivos desde cualquier URL, lo que puede introducir vulnerabilidades de seguridad en tu aplicación dockerizada. Por eso, recomiendo evitar el comando `ADD` en los Dockerfile para incluir dependencias remotas.
En su lugar, usa el comando COPY para copiar archivos desde el sistema de archivos local. El comando COPY garantiza que solo se incluyan en la imagen Docker los archivos necesarios para la aplicación. De nuevo, esto ayuda a reducir el riesgo de vulnerabilidades.
Usa un archivo YAML de docker-compose
Docker Compose te permite administrar y orquestar tus contenedores Docker mediante la definición de tu aplicación Docker en un archivo YAML y la especificación de cómo debe compilarse y ejecutarse. Algunos beneficios de usar Docker Compose son:
Separar los componentes de la aplicación. Docker Compose te permite separar los componentes de tu aplicación en distintos contenedores. Esto limita la superficie de ataque de cada contenedor y reduce el riesgo de un único punto de falla.
Usar variables de entorno. Docker Compose te permite usar variables de entorno para configurar tu aplicación, lo que puede ayudarte a administrar de forma segura información confidencial, como las contraseñas de bases de datos.
Administrar las conexiones de red. Docker Compose te permite administrar las conexiones de red entre tus contenedores. Esto garantiza que solo puedan comunicarse entre sí mediante un canal seguro.
Si instalaste Docker Desktop para Windows, Mac o Linux, ya tienes Docker Compose.
Usa PHP-FPM, no mod_php
PHP-FPM y mod_php son soluciones para ejecutar aplicaciones PHP en servidores web, pero funcionan de manera diferente. mod_php es un módulo de Apache que permite que el servidor web Apache procese archivos PHP, mientras que PHP-FPM es un administrador de procesos PHP que funciona con varios servidores web, incluidos NGINX y Apache.
Por lo general, PHP-FPM se considera una forma más eficiente y escalable de ejecutar aplicaciones PHP, especialmente en entornos con mucho tráfico.
Usa compilaciones de varias etapas
Las compilaciones de varias etapas son una técnica de Docker para crear imágenes más pequeñas y seguras. Al crear varias etapas dentro de un Dockerfile, cada una con sus propias instrucciones, no tienes que volver a compilar toda la imagen desde cero cada vez que haces un cambio. Como resultado, mejoras la eficiencia y la velocidad del proceso de compilación de Docker.
Prueba siempre la seguridad de tu aplicación dockerizada
Las pruebas de seguridad frecuentes son fundamentales para garantizar y mejorar la seguridad de tu aplicación. Aunque Docker ofrece un entorno aislado para ejecutarla, eso no garantiza que sea segura. Realiza comprobaciones de seguridad periódicas para identificar y abordar posibles vulnerabilidades antes de que los atacantes puedan aprovecharlas.
Cinco pasos para dockerizar tu aplicación PHP de forma segura
¡Pasemos a la parte práctica! En el siguiente tutorial, te guiaremos por cinco pasos para dockerizar de forma segura una aplicación PHP de Laravel, con algunos de los consejos que acabamos de ver.
1. Configura el Dockerfile con Apache
Si todavía no tienes un proyecto, crea un nuevo proyecto de Laravel y cambia al directorio del proyecto con cd. Por ejemplo, en el siguiente comando, reemplaza {{laravel-application-directory}} por el nombre del directorio de tu aplicación Laravel.
Crea un archivo llamado Dockerfile en el directorio raíz de tu aplicación Laravel:
Copia y pega el siguiente código en el Dockerfile que acabas de crear:
Aunque, como se indicó anteriormente, PHP-FPM es la mejor opción para compilar una solución escalable, este tutorial usa mod_php porque la aplicación es pequeña.
También observa que el contenido del Dockerfile anterior usa compilaciones de varias etapas. La primera etapa usa la imagen oficial de Composer para instalar las dependencias de la aplicación y compilar el autocargador. La segunda etapa usa la imagen oficial de PHP/Apache para ejecutar la aplicación. Ten en cuenta que se usa el comando COPY para copiar los archivos de compilación de Composer desde el sistema de archivos local, no el comando ADD.
Crea un archivo llamado docker-compose.yml en el directorio raíz de tu aplicación Laravel:
Copia y pega el siguiente código en el archivo docker-compose.yml que acabas de crear:
En el código anterior, el servicio snykdemoapp es el contenedor de la aplicación PHP. Además, la sección de redes define app-network, que Docker Compose usará para la comunicación.
2. Configura un contenedor de base de datos MySQL en docker-compose.yml
Agreguemos un contenedor MySQL a tu archivo docker-compose.yml. Este contenedor alojará la base de datos de tu aplicación Laravel.
Crea un servicio para tu contenedor MySQL agregando el siguiente código como nuevo servicio al archivo docker-compose.yml que creaste en el primer paso:
En el bloque de código anterior:
app_dbes el nombre del servicio de base de datos, creado con la imagen de MySQL versión 5.7. Puedes cambiar el nombre como prefieras, pero asegúrate de actualizarlo en los demás servicios que estén vinculados.{{database_name}}es el nombre de base de datos que prefieras.{{database_user}}es el usuario de base de datos que prefieras.{{dbuser_password}}es la contraseña que prefieras para el usuario de base de datos.
¡Listo! Agregaste correctamente un contenedor MySQL a tu configuración de Docker.
3. Configura un contenedor de PHPMyAdmin en docker-compose.yml
Ahora agreguemos un contenedor de PHPMyAdmin para pruebas y desarrollo local, junto con tus contenedores de Laravel y MySQL. PHPMyAdmin es una herramienta de administración gratuita y de código abierto para MySQL y MariaDB. Ofrece una interfaz web para administrar tus bases de datos. Se recomienda usar PHPMyAdmin solo durante el desarrollo, no en producción.
Crea un servicio para tu contenedor de PHPMyAdmin agregando el siguiente fragmento de código como nuevo servicio a docker-compose.yml.
En el bloque de código anterior, phpmyadmin es el nombre del servicio de PHPMyAdmin, creado con la imagen phpmyadmin/phpmyadmin. La sección de entorno establece la variable PMA_HOST en app_db, que es el nombre del servicio MySQL en el mismo archivo docker-compose.yml.
Ahora tienes un contenedor de PHPMyAdmin configurado para funcionar con tus contenedores de Laravel y MySQL. Ten en cuenta que la imagen de PHPMyAdmin solo debe usarse con fines de desarrollo. Usarla en producción supone un riesgo de seguridad para tu aplicación.
4. Compila y ejecuta la aplicación PHP de Laravel con Docker
Ahora que configuraste el Dockerfile y docker-compose.yml, inicia el servicio Docker y asegúrate de que esté en ejecución. Luego, puedes compilar y ejecutar la aplicación PHP de Laravel con los siguientes comandos:
docker-compose build: compila la imagen Docker.docker-compose up -d: inicia los contenedores.docker ps: comprueba el estado del contenedor.
Si todos los comandos anteriores se ejecutan correctamente, abre el navegador y ve a http://localhost:8000/ para acceder a la página principal de tu aplicación Laravel.

También puedes ir a http://localhost:8080/ para acceder a la interfaz de PHPAdmin. Puedes usar MYSQL_USER y MYSQL_PASSWORD, que configuraste en el archivo docker-compose.yml, para iniciar sesión.

5. Prueba y protege tu aplicación PHP con Snyk
Cuando hayas compilado correctamente tu aplicación Docker y puedas acceder tanto a ella como a PHPMyAdmin desde el navegador, el siguiente paso es probar su seguridad. En este tutorial se usa Snyk para probar y garantizar que la aplicación dockerizada esté completamente protegida.
Inicia sesión o crea una cuenta de Snyk con cualquiera de las opciones de SSO que aparecen en la página. Instala Snyk CL y autentica tu laptop, como se indica en la sección de requisitos previos de este artículo.

Una vez que hayas configurado Snyk, usa Snyk CLI para evaluar la seguridad de tu aplicación dockerizada. Ejecuta el siguiente comando en el directorio raíz de tu aplicación Laravel:
En la línea anterior, {{your-image}} es el nombre de la imagen que quieres probar. Puedes usar el comando `docker ps` para obtener una lista de las imágenes Docker de tu aplicación.
Al ejecutar el comando anterior en la imagen base PHP 8.2 llamada snykdemoapp que se usa en este tutorial, obtendrás lo siguiente:

PHP 8.2 es la versión más reciente con soporte a largo plazo. Aunque se encontraron 69 problemas de seguridad en la imagen base de este contenedor, todos son de gravedad baja.
Si usaras versiones anteriores de PHP en tus aplicaciones de producción, como PHP 7.4, encontrarías vulnerabilidades de seguridad más graves y urgentes que requieren atención. En este caso, Snyk es aún más útil porque te ofrece tipos de imágenes alternativos con menos vulnerabilidades.
El comando snyk container test solo ofrece un resultado puntual. Una mejor opción es ejecutar el comando container monitor para analizar el contenedor.
El comando container monitor envía a Snyk la información de las pruebas de la imagen de tu contenedor. Así, Snyk puede mostrarla en tu panel y notificarte sobre posibles vulnerabilidades futuras en la imagen.
Al ejecutar container monitor en la imagen base PHP 7.4 llamada snykdemoapp.

Cómo corregir las vulnerabilidades detectadas en tu aplicación PHP
Ahora que probaste tu contenedor de PHP, aquí tienes algunos consejos para corregir las vulnerabilidades detectadas.
Vuelve a crear la imagen para obtener las actualizaciones de seguridad más recientes de la imagen base de Docker original. Así te aseguras de que tu aplicación incluya todas las actualizaciones de seguridad. Después de volver a crear la imagen, ejecuta el análisis de seguridad otra vez para identificar y corregir las vulnerabilidades que puedan venir con las actualizaciones de seguridad más recientes de la imagen base.
Consulta la evaluación de vulnerabilidades que ofrece Snyk. Esta lista puede proporcionar información útil sobre posibles problemas de seguridad en las dependencias de la aplicación.
Ten en cuenta que las vulnerabilidades pueden provenir de distintas fuentes. Entre ellas se encuentran el entorno de ejecución de PHP, así como las herramientas y bibliotecas instaladas en la imagen base. Es fundamental actualizar y monitorear periódicamente todos los componentes de la pila de la aplicación para identificar y corregir cuanto antes cualquier vulnerabilidad de seguridad.
Conclusión
Seguir algunas prácticas recomendadas puede ayudarte a desarrollar aplicaciones con menos vulnerabilidades. Si completaste el tutorial paso a paso, deberías poder desarrollar de forma segura una aplicación PHP en Docker, usando la plataforma de seguridad de Snyk para detectar y corregir vulnerabilidades.
Puedes encontrar en GitHub todo el código que se usó para la aplicación Laravel en Docker de este tutorial.
Seguridad de contenedores centrada en los desarrolladores
Snyk encuentra y corrige automáticamente vulnerabilidades en imágenes de contenedores y cargas de trabajo de Kubernetes.



