Gestionar secretos de forma segura en Docker Compose
Un secreto es cualquier dato, como una contraseña, certificado o clave de API, que no debe transmitirse a través de una red ni almacenarse sin cifrar en un Dockerfile o en el código fuente de tu aplicación.
Docker Compose te ofrece una forma de usar secretos (secrets) sin tener que utilizar variables de entorno para almacenar información. Si inyectas contraseñas y claves de API como variables de entorno, te arriesgas a la exposición no intencionada de información. Los servicios solo pueden acceder a los secretos si se les concede acceso explícitamente mediante un atributo secrets dentro del elemento de nivel superior services.
Las variables de entorno a menudo están disponibles para todos los procesos y puede resultar difícil rastrear su acceso. También pueden imprimirse en los registros (logs) al depurar errores sin tu conocimiento. El uso de secretos mitiga estos riesgos.
Usar secretos
Los secretos se montan como un archivo en /run/secrets/<secret_name> dentro del contenedor.
Llevar un secreto a un contenedor es un proceso de dos pasos. Primero, define el secreto utilizando el
elemento de nivel superior secrets en tu archivo de Compose. A continuación, actualiza las definiciones de tus servicios para hacer referencia a los secretos que requieren mediante el
atributo secrets. Compose otorga acceso a los secretos por servicio.
A diferencia de otros métodos, esto permite un control de acceso granular dentro del contenedor de un servicio mediante los permisos estándar del sistema de archivos.
Ejemplos
Inyección de secretos en un solo servicio
En el siguiente ejemplo, al servicio frontend se le otorga acceso al secreto my_secret. En el contenedor, /run/secrets/my_secret se establece con el contenido del archivo ./my_secret.txt.
services:
myapp:
image: myapp:latest
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret.txtIntercambio de secretos entre múltiples servicios y gestión de contraseñas
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: db_password.txt
db_root_password:
file: db_root_password.txt
volumes:
db_data:En el ejemplo avanzado anterior:
- El atributo
secretsbajo cada servicio define los secretos que deseas inyectar en el contenedor específico. - La sección
secretsa nivel superior define las variablesdb_passwordanddb_root_passwordy proporciona el archivo (file) que aporta sus valores. - El despliegue de cada contenedor implica que Docker crea un montaje de vinculación (bind mount) bajo
/run/secrets/<secret_name>con sus valores específicos.
Note
Secretos de compilación (Build secrets)
En el siguiente ejemplo, el secreto npm_token se pone a disposición en tiempo de compilación. Su valor se toma de la variable de entorno NPM_TOKEN.
services:
myapp:
build:
secrets:
- npm_token
context: .
secrets:
npm_token:
environment: NPM_TOKEN