¿Cómo instalar extensiones PHP en Docker?

Estás arrancando la dockerización de tu aplicación PHP.

Como para probar un poco, arrancaste un contenedor usando un comando:

docker run -v $(pwd):/app -it php:latest index.php

Y ahí nomás te encontraste con el primero de los problemas:

PHP Fatal error: Uncaught Error: Class "ZipArchive" not found

Claro! Tu aplicación necesita de la extensión Zip para funcionar! ¿Y ahora?

Bueno, a no desesperar.

Tenés varias opciones disponibles:

  1. Buscar una imagen que ya tenga la extensión zip instalada
  2. Agregar las instrucciones para que se compile e instale la extensión durante el build de la imagen
  3. Usar un script de instalación

Para el resto de los ejemplos tomaré una versión hiper simplificada de lo que puede ser tu aplicación:

<?php

$zip = new ZipArchive();
if ($zip->open($argv[1]) == TRUE) {
 for ($i = 0; $i < $zip->numFiles; $i++) {
     echo $zip->getNameIndex($i).PHP_EOL;
 }
}

Y asumiré que tienes un archivo comprimido llamado compressed.zip.

Una imagen Docker PHP con la extensión zip

Seguramente habrá muchas opciones, una de ellas, como para salir del paso, es thecodingmachine/php:7.3-v4-slim-cli (Podés encontrar otras similares acá).

Para usarla este comando puede ser útil: docker run -v $(pwd):/usr/src/app --rm -it thecodingmachine/php:7.3-v4-slim-cli php index.php compressed.zip

Como decía, esta solución no es ni de lejos la mejor.

¿Por qué? Básicamente porque tenés muy poco control sobre lo que tiene la imágen. En otras palabras, no sabés muy bien qué otras cosas te estás trayendo además de la extensión zip.

En el mejor de los casos vas a terminar con una imagen más grande de lo necesario.

En el peor vas a incluir extensiones que no necesitás y exponerte a riesgos de seguridad.

Mejor seguir leyendo.

Compilar la extensión zip dentro del build de la imagen

Una forma de contar con la extensión zip (o cualquier otra en realidad) en tu contenedor es compilar php de modo que lo tenga incorporado.

Por ejemplo, usando un Dockerfile como este:

FROM ubuntu:latest

ADD https://www.php.net/distributions/php-8.4.1.tar.gz /php/php.tar.gz
RUN apt-get update && \
        apt-get install -y libzip-dev build-essential pkg-config libxml2-dev libsqlite3-dev && \
        tar xzf /php/php.tar.gz -C /php/ && \
        cd /php/php-8.4.1/ && \
        ./configure --prefix=/usr/local/php-8.4.1 --with-zip && \
        make && make install && \
        ln -s /usr/local/php-8.4.1/bin/php /usr/local/bin
WORKDIR /app

Y construtendo la imagen usando docker build . -t php-zip

Podrías ejecutar tu script usando: docker run -v $(pwd):/app --rm -it php-zip php index.php compressed.zip

Y no verás el error que estaba al comienzo.

Esta opción, si bien es más correcta que la primera, puede resultar un poco overkill. Particularmente, si tenés que instalar varias extensiones, llegar al Dockerfile correcto puede ser bastante laborioso.

En la siguiente sección te doy la que personalmente recomiendo

Un script de instalación de extensiones PHP para Docker

Bueno, en realidad no es un script de instalación si no dos.

Arranco por el más conocido: php-ext-install.

Lo bueno de este script es que, si partís de una imagen oficial de php, no tenés que hacer nada para tenerlo disponible.

Lo malo de este script es que requiere bastante ayuda para hacer lo suyo.

Por ejemplo, instalar la extensión zip implica agregar a tu Dockerfile:

RUN docker-php-ext-install zip

Pero… con eso sólo no alcanza. Si lo intentas, al hacer el build verás este error:

Package 'libzip', required by 'virtual:world', not found
Package 'libzip', required by 'virtual:world', not found
Package 'libzip', required by 'virtual:world', not found

Lo que quiere decir que necesitas, antes de esto, instalar la librería zip.

En definitiva, el Dockerfile que te dará lo que buscas es uno que se parezca a:

FROM php:8.4.1-cli

RUN apt update && apt-get install -y libzip-dev && docker-php-ext-install zip

En este caso no ha sido tan terrible, cierto, pero hay otras extensiones que también requieren ciertos cambios en configuraciones. Nada del otro mundo pero es algo más que hay que recordar.

El script que me gusta más, y el que recomiendo usar, es docker-php-extension-installer.

A diferencia del primero, docker-php-extension-installer debe ser instalado explícitamente pero, una vez instalado, es mucho más cómodo.

Aquí un ejemplo de Dockerfile para la extensión zip:

FROM php:8.4.1-cli

ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN install-php-extensions zip

WORKDIR /app

Nuevamente, ejecutando docker run -v $(pwd):/app --rm -it php-zip php index.php compressed.zip verás el listado de los archivos contenidos en el archivo comprimido.

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a afinar sus habilidades técnicas y avanzar en sus carreras

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.