Implementación de NGINX y NGINX Plus con Docker

NGINX | 09 de noviembre de 2021


Editor – Los Dockerfiles de NGINX Plus para Alpine Linux y Debian se actualizaron en noviembre de 2021 para incorporar las versiones más recientes del software. Además, junto con las instrucciones revisadas, utilizan secretos de Docker para proporcionar la información de licencia al crear una imagen de NGINX Plus.

Docker es una plataforma abierta para crear, distribuir y ejecutar aplicaciones distribuidas como contenedores (paquetes de software ligeros, autónomos y ejecutables que incluyen todo lo necesario para ejecutar una aplicación). A su vez, los contenedores pueden implementarse y gestionarse mediante plataformas de orquestación de contenedores como Kubernetes. (Además de la tecnología de contenedores Docker analizada en este blog, NGINX ofrece F5 NGINX Ingress Controller en versiones basadas en NGINX Open Source y NGINX Plus; para los suscriptores de NGINX Plus, el soporte está incluido sin coste adicional).

Como aplicaciones de software, NGINX Open Source y F5 NGINX Plus son casos de uso ideales para Docker, y publicamos una imagen de NGINX Open Source en Docker Hub, el repositorio de imágenes de Docker. En este artículo se explica cómo:

Introducción

La plataforma abierta Docker incluye Docker Engine, el entorno de ejecución de código abierto que crea, ejecuta y orquesta contenedores, y Docker Hub, un servicio alojado en el que toda la comunidad de desarrolladores, o bien los miembros de una organización específica, pueden distribuir, compartir y desarrollar conjuntamente aplicaciones dockerizadas.

Los contenedores Docker permiten a los desarrolladores centrar sus esfuerzos en el «contenido» de las aplicaciones al desvincularlas de las limitaciones de la infraestructura. Las aplicaciones dockerizadas se pueden trasladar al instante a cualquier infraestructura —portátil, servidor físico, máquina virtual o nube—, lo que las convierte en componentes modulares que pueden ensamblarse y reorganizarse fácilmente para crear aplicaciones distribuidas con todas las funcionalidades, además de evolucionar continuamente en tiempo real.

Para obtener más información sobre Docker, consulta ¿Por qué Docker? o la documentación completa de Docker.

Uso de la imagen de Docker de NGINX Open Source

Puede crear una instancia de NGINX en un contenedor Docker utilizando la imagen de NGINX Open Source de Docker Hub.

Empecemos con un ejemplo muy sencillo. Para iniciar una instancia de NGINX que se ejecute en un contenedor y utilice la configuración predeterminada de NGINX, ejecute este comando:

# docker run --name mynginx1 -p 80:80 -d nginxfcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d

Este comando crea un contenedor llamado mynginx1 basado en la imagen de NGINX. El comando devuelve la versión larga del ID del contenedor, que se utiliza en el nombre de los archivos de registro; consulte Gestión de registros.

La opción -p indica a Docker que asigne el puerto expuesto en el contenedor por la imagen de NGINX (el puerto 80) al puerto especificado en el host de Docker. El primer parámetro especifica el puerto del host de Docker, mientras que el segundo se asigna al puerto expuesto en el contenedor.

La opción -d especifica que el contenedor se ejecuta en modo desacoplado, lo que significa que continúa ejecutándose hasta que se detiene, pero no responde a los comandos ejecutados en la línea de comandos. En la siguiente sección explicamos cómo interactuar con el contenedor.

Para comprobar que el contenedor se ha creado y está en ejecución, así como para ver las asignaciones de puertos, ejecutamos docker ps. (Aquí hemos dividido la salida en varias líneas para facilitar su lectura).

# docker psCONTAINER ID  IMAGE         COMMAND               CREATED         STATUS        ...  
fcd1fb01b145  nginx:latest  "nginx -g 'daemon of  16 seconds ago  Up 15 seconds ... 

    ... PORTS              NAMES
    ... 0.0.0.0:80->80/tcp mynginx1

El campo PORTS de la salida indica que el puerto 80 del host de Docker está asignado al puerto 80 del contenedor. Otra forma de comprobar que NGINX se está ejecutando es realizar una solicitud HTTP a ese puerto. Aparece el código de la página de bienvenida predeterminada de NGINX:

# curl http://localhost<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
 body {
 width: 35em;
 margin: 0 auto;
 font-family: Tahoma, Verdana, Arial, sans-serif;
 }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="https://www.nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Trabajar con el contenedor Docker de NGINX

Ahora tenemos un contenedor Docker de NGINX en funcionamiento, pero ¿cómo gestionamos el contenido y la configuración de NGINX? ¿Y qué ocurre con los registros?

Una nota sobre SSH

Es habitual habilitar el acceso SSH a las instancias de NGINX, pero la imagen de NGINX no tiene OpenSSH instalado, ya que los contenedores Docker suelen estar diseñados para un único propósito (en este caso, ejecutar NGINX). En su lugar, utilizaremos otros métodos compatibles con Docker.

Como alternativa a los comandos que se indican a continuación, puede ejecutar el siguiente comando para abrir un shell interactivo en un contenedor NGINX en ejecución (en lugar de iniciar una sesión SSH). No obstante, solo recomendamos esta opción a usuarios avanzados.

  • En sistemas Alpine Linux:
# docker exec -it NGINX_container_ID sh
  • En sistemas Debian:
# docker exec -it NGINX_container_ID bash

Gestión de archivos de contenido y configuración

Hay varias formas de gestionar tanto el contenido servido por NGINX como los archivos de configuración de NGINX. A continuación, explicamos algunas de las opciones.

Opción 1: mantener el contenido y la configuración en el host de Docker

Al crear el contenedor, podemos indicar a Docker que monte un directorio local del host de Docker en un directorio del contenedor. La imagen de NGINX utiliza la configuración predeterminada de NGINX, que establece /usr/share/nginx/html como directorio raíz del contenedor y almacena los archivos de configuración en /etc/nginx. Para un host de Docker cuyo contenido se encuentre en el directorio local /var/www y cuyos archivos de configuración estén en /var/nginx/conf, ejecute este comando (que aquí aparece en varias líneas únicamente para facilitar su lectura):

# docker run --name mynginx2 --mount type=bind source=/var/www,target=/usr/share/nginx/html,readonly --mount type=bind,source=/var/nginx/conf,target=/etc/nginx/conf,readonly -p 80:80 -d nginx

Ahora, cualquier cambio realizado en los archivos de los directorios locales /var/www y /var/nginx/conf del host de Docker se refleja en los directorios /usr/share/nginx/html y /etc/nginx del contenedor. La opción readonly significa que estos directorios solo se pueden modificar en el host de Docker, no desde el interior del contenedor.

Opción 2 – Copiar archivos desde el host de Docker

Otra opción consiste en hacer que Docker copie los archivos de contenido y configuración desde un directorio local del host de Docker durante la creación del contenedor. Una vez creado el contenedor, los archivos se mantienen creando un nuevo contenedor cuando cambian o modificándolos en el propio contenedor. Una forma sencilla de copiar los archivos es crear un archivo Dockerfile con comandos que se ejecutan durante la generación de una nueva imagen de Docker basada en la imagen de NGINX de Docker Hub. En los comandos de copia de archivos (COPY) del archivo Dockerfile, la ruta del directorio local es relativa al contexto de compilación en el que se encuentra el archivo Dockerfile.

En nuestro ejemplo, el contenido se encuentra en el directorio content y los archivos de configuración se encuentran en el directorio conf, ambos subdirectorios del directorio donde se encuentra el archivo Dockerfile. La imagen de NGINX incluye archivos de configuración predeterminados de NGINX en /etc/nginx/nginx.conf y /etc/nginx/conf.d/default.conf. Como queremos utilizar los archivos de configuración del host, incluimos un comando RUN que elimina los archivos predeterminados:

FROM nginx
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx

Creamos nuestra propia imagen de NGINX ejecutando el siguiente comando desde el directorio en el que se encuentra el archivo Dockerfile. Observe el punto («.») al final del comando. Este establece el directorio actual como contexto de compilación, que contiene el archivo Dockerfile y los directorios que se van a copiar.

# docker build -t mynginx_image1 .

Ahora ejecutamos este comando para crear un contenedor llamado mynginx3 basado en la imagen mynginx_image1:

# docker run --name mynginx3 -p 80:80 -d mynginx_image1

Si queremos realizar cambios en los archivos del contenedor, utilizamos un contenedor auxiliar, tal como se describe en la opción 3.

Opción 3 – Mantener los archivos en el contenedor

Como se menciona en «Nota sobre SSH», no podemos usar SSH para acceder al contenedor de NGINX, por lo que, si queremos editar directamente los archivos de contenido o configuración, debemos crear un contenedor auxiliar que tenga acceso mediante shell. Para que el contenedor auxiliar pueda acceder a los archivos, debemos crear una imagen nueva que tenga definidos los volúmenes de datos de Docker adecuados. Suponiendo que queramos copiar archivos como en la opción 2 y, al mismo tiempo, definir volúmenes, utilizaremos el siguiente Dockerfile:

FROM nginxRUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /usr/share/nginx/html
VOLUME /etc/nginx

A continuación, creamos la nueva imagen de NGINX ejecutando el siguiente comando (de nuevo, fíjese en el punto final):

# docker build -t mynginx_image2 .

Ahora ejecutamos este comando para crear un contenedor NGINX (mynginx4) basado en la imagen mynginx_image2:

# docker run --name mynginx4 -p 80:80 -d mynginx_image2

A continuación, ejecutamos el siguiente comando para iniciar un contenedor auxiliar llamado «mynginx4_files» que dispone de un intérprete de comandos, lo que nos permite acceder a los directorios de contenido y configuración del contenedor «mynginx4» que acabamos de crear:

# docker run -i -t --volumes-from mynginx4 --name mynginx4_files debian /bin/bashroot@b1cbbad63dd1:/#

El nuevo contenedor auxiliar mynginx4_files se ejecuta en primer plano con una entrada estándar persistente (la opción -i) y una tty (la opción -t). Todos los volúmenes definidos en mynginx4 se montan como directorios locales en el contenedor auxiliar.

El argumento «debian» significa que el contenedor auxiliar utiliza la imagen de Debian de Docker Hub. Dado que la imagen de NGINX también utiliza Debian (y todos nuestros ejemplos hasta ahora utilizan la imagen de NGINX), resulta más eficiente utilizar Debian para el contenedor auxiliar que hacer que Docker cargue otro sistema operativo. El argumento «/bin/bash» significa que el shell bash se ejecuta en el contenedor auxiliar y muestra un indicador de comandos que puede utilizar para modificar los archivos según sea necesario.

Para iniciar y detener el contenedor, ejecute los siguientes comandos:

# docker start mynginx4_files# docker stop mynginx4_files

Para salir del shell sin detener el contenedor, pulsa Ctrl+p y, a continuación, Ctrl+q. Para volver a acceder al shell de un contenedor en ejecución, ejecuta este comando:

# docker attach mynginx4_files

Para salir del shell y detener el contenedor, ejecuta el comando exit.

Gestión de registros

Puede configurar el registro predeterminado o uno personalizado.

Uso del registro predeterminado

La imagen de NGINX está configurada de forma predeterminada para enviar los registros principales de acceso y errores de NGINX al recopilador de registros de Docker. Para ello, se enlazan respectivamente con stdout y stderr; a continuación, todos los mensajes de ambos registros se escriben en el archivo /var/lib/docker/containers/container-ID/container-ID-json.log del host de Docker, donde container‑ID es el ID completo que se devuelve al crear un contenedor. Por ejemplo, para el contenedor inicial que creamos en Uso de la imagen de Docker de NGINX Open Source, es fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d.

Para obtener el ID de contenedor de un contenedor existente, ejecute este comando, donde container‑name es el valor establecido mediante el parámetro --name al crear el contenedor (por ejemplo, para el ID de contenedor anterior, es mynginx1):

# docker inspect --format '{{ .Id }}' container-name

Aunque puedes consultar los registros abriendo directamente el archivo container-ID-json.log, normalmente es más fácil ejecutar este comando:

# docker logs container-name

También puedes usar la API de Docker Engine para extraer los mensajes de registro mediante una solicitud GET al socket Unix de Docker. Este comando devuelve tanto el registro de acceso (representado por stdout=1) como el registro de errores (stderr=1), aunque también puedes solicitarlos por separado:

curl --unix-socket /var/run/docker-sock http://localhost/containers/container-name/logs?stdout=1&stderr=1

Para obtener información sobre otros parámetros de consulta, consulta la documentación de la API de Docker Engine (busca «Get container logs» en esa página).

Uso del registro personalizado

Si desea implementar otro método de recopilación de registros o configurar el registro de forma diferente en determinados bloques de configuración (como server{} y location{}), defina un volumen de Docker para el directorio o los directorios en los que se almacenarán los archivos de registro del contenedor, cree un contenedor auxiliar para acceder a dichos archivos y utilice las herramientas de registro que prefiera. Para ello, cree una nueva imagen que contenga el volumen o los volúmenes destinados a los archivos de registro.

Por ejemplo, para configurar NGINX de modo que almacene los archivos de registro en /var/log/nginx/log, podemos partir del Dockerfile de la opción 3 y simplemente añadir una definición VOLUME para este directorio:

FROM nginxRUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /var/log/nginx/log

A continuación, podemos crear una imagen como se ha descrito anteriormente y utilizarla para crear un contenedor NGINX y un contenedor auxiliar que tengan acceso al directorio de registros. En el contenedor auxiliar se pueden instalar las herramientas de registro que se deseen.

Control de NGINX

Como no tenemos acceso directo a la línea de comandos del contenedor de NGINX, no podemos usar el comando «nginx» para controlar NGINX. Afortunadamente, podemos usar señales para controlar NGINX, y Docker proporciona el comando «kill» para enviar señales a un contenedor.

Para volver a cargar la configuración de NGINX, ejecuta este comando:

# docker kill -s HUP container-name

Para reiniciar NGINX, ejecuta este comando para reiniciar el contenedor:

# docker restart container-name

Implementación de NGINX Plus con Docker

Hasta ahora hemos hablado de Docker para NGINX Open Source, pero también puede utilizarlo con el producto comercial NGINX Plus. La diferencia es que primero debe crear una imagen de NGINX Plus, ya que, al tratarse de una oferta comercial, NGINX Plus no está disponible en Docker Hub. Afortunadamente, es bastante fácil hacerlo.

Nota: No suba nunca sus imágenes de NGINX Plus a un repositorio público como Docker Hub. Si lo hace, estará incumpliendo el contrato de licencia.

Crear una imagen de Docker de NGINX Plus

Para generar una imagen de NGINX Plus, primero cree un archivo Dockerfile. Los ejemplos que se proporcionan aquí utilizan Alpine Linux 3.14 y Debian 11 (Bullseye) como imágenes base de Docker. Antes de crear la imagen de Docker de NGINX Plus, debe descargar su versión de los archivos nginx-repo.crt y nginx-repo.key. Los clientes de NGINX Plus pueden encontrarlos en el portal del cliente; si está realizando una prueba gratuita de NGINX Plus, se incluyen en el paquete de prueba. Copie los archivos en el directorio donde se encuentra el archivo Dockerfile (el contexto de compilación de Docker).

Al igual que con NGINX Open Source, de forma predeterminada, los registros de acceso y de errores de NGINX Plus están vinculados al recopilador de registros de Docker. No se especifica ningún volumen, pero puede añadirlos si lo desea, o bien puede utilizar cada Dockerfile para crear imágenes base a partir de las cuales crear nuevas imágenes con los volúmenes especificados, como se ha descrito anteriormente.

No especificamos deliberadamente ninguna versión de NGINX Plus en los Dockerfile de ejemplo, para que no tenga que editar el archivo cuando actualice a una nueva versión de NGINX Plus. No obstante, hemos incluido versiones comentadas de las instrucciones pertinentes para que pueda quitarles los comentarios si desea que el archivo sea específico de una versión.

Del mismo modo, hemos incluido instrucciones (comentadas) para instalar módulos dinámicos oficiales para NGINX Plus.

De forma predeterminada, no se copia ningún archivo del host de Docker al crear un contenedor. Puede añadir definiciones COPY a cada Dockerfile, o bien utilizar la imagen que cree como base para otra imagen, tal como se ha descrito anteriormente.

Dockerfile de NGINX Plus (Debian 11)

Cargando ejemplo de código…

Dockerfile de NGINX Plus (Alpine Linux 3.14)

Cargando ejemplo de código…

Creación de la imagen de NGINX Plus

Con el archivo Dockerfile, nginx-repo.crt y nginx-repo.key en el mismo directorio, ejecute allí el siguiente comando para crear una imagen de Docker llamada nginxplus (como antes, tenga en cuenta el punto final):

# DOCKER_BUILDKIT=1 docker build --no-cache -t nginxplus --secret id=nginx-crt,src=your_cert_file --secret id=nginx-key,src=your_key_file .

La opción DOCKER_BUILDKIT=1 indica que estamos utilizando Docker BuildKit para compilar la imagen, tal como se requiere al incluir la opción --secret, que se explica a continuación.

La opción --no-cache indica a Docker que cree la imagen desde cero y garantiza la instalación de la versión más reciente de NGINX Plus. Si el Dockerfile se utilizó anteriormente para crear una imagen y no se incluye la opción --no-cache, la nueva imagen utiliza la versión de NGINX Plus de la caché de Docker. (Como se ha indicado, no especificamos deliberadamente una versión de NGINX Plus en el Dockerfile para que no sea necesario modificar el archivo con cada nueva versión de NGINX Plus). Omita la opción --no-cache si resulta aceptable utilizar la versión de NGINX Plus de la imagen creada anteriormente.

La opción --secret pasa el certificado y la clave de su licencia de NGINX Plus al contexto de compilación de Docker sin riesgo de exponer los datos ni de que estos persistan entre las capas de compilación de Docker. Los valores de los argumentos id no se pueden cambiar sin modificar el Dockerfile base, pero debe establecer los argumentos src en la ruta de los archivos de certificado y clave de NGINX Plus (el mismo directorio en el que está compilando la imagen de Docker si ha seguido las instrucciones anteriores).

Una salida como la siguiente del comando «docker images nginxplus» indica que la imagen se ha creado correctamente:

# docker images nginxplus
REPOSITORY  TAG     IMAGE ID      CREATED        VIRTUAL SIZE
nginxplus   latest  ef2bf65931cf  6 seconds ago  91.2 MB

Para crear un contenedor llamado mynginxplus basado en esta imagen, ejecute el siguiente comando:

# docker run --name mynginxplus -p 80:80 -d nginxplus

Puede controlar y gestionar los contenedores de NGINX Plus de la misma forma que los contenedores de NGINX Open Source.

Resumen

NGINX, NGINX Plus y Docker funcionan extraordinariamente bien juntos. Tanto si utiliza la imagen de NGINX Open Source de Docker Hub como si crea su propia imagen de NGINX Plus, puede poner en marcha fácilmente nuevas instancias de NGINX y NGINX Plus en contenedores de Docker e implementarlas en su entorno de Kubernetes. También puede crear fácilmente nuevas imágenes de Docker a partir de las imágenes base, lo que facilita aún más el control y la gestión de sus contenedores. Asegúrese de que todas las instancias de NGINX Plus que se ejecuten en sus contenedores de Docker estén cubiertas por su suscripción. Para obtener más información, póngase en contacto con el equipo de ventas de NGINX.

Docker ofrece mucho más de lo que hemos podido abordar en este artículo. Para obtener más información, descargue gratis nuestro libro electrónico de O’Reilly – Redes de contenedores: de Docker a Kubernetes – o visite www.docker.com.

Documentación relacionada

Implementación de NGINX y NGINX Plus en Docker


Compartir
Etiquetas: F5 NGINX, 2021, Tech

Sobre el autor

Rick Nelson
Rick NelsonVicepresidente regional de Ingeniería de Soluciones

Más artículos de Rick Nelson

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.