Estoy ejecutando docker-container en Amazon EC2. Actualmente he agregado credenciales de AWS a Dockerfile. ¿Podría por favor decirme la mejor manera de hacer esto?
Otro enfoque es pasar las claves de la máquina host al contenedor docker. Puede agregar las siguientes líneas al archivo docker-compose .
services: web: build: . environment: - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}Otro enfoque más es crear un volumen temporal de solo lectura en docker-compose.yaml. AWS CLI y SDK (como boto3 o AWS SDK para Java, etc.) buscan un perfil default en el archivo ~/.aws/credentials .
Si desea utilizar otros perfiles, solo necesita exportar la variable AWS_PROFILE antes de ejecutar el comando docker-compose .
export AWS_PROFILE=some_other_profile_name
version: '3' services: service-name: image: docker-image-name:latest environment: - AWS_PROFILE=${AWS_PROFILE} volumes: - ~/.aws/:/root/.aws:ro En este ejemplo, utilicé el usuario raíz en la ventana acoplable. Si está utilizando otro usuario, simplemente cambie /root/.aws al directorio de inicio del usuario.
:ro - significa volumen acoplable de solo lectura
Es muy útil cuando tiene varios perfiles en el archivo ~/.aws/credentials y también usa MFA. También es útil cuando desea probar localmente el contenedor acoplable antes de implementarlo en ECS en el que tiene roles de IAM, pero localmente no los tiene.
Mucho ha cambiado en Docker desde que se hizo esta pregunta, así que aquí hay un intento de una respuesta actualizada.
Primero, específicamente con las credenciales de AWS en contenedores que ya se ejecutan dentro de la nube, usar roles de IAM como sugiere Vor es una muy buena opción. Si puede hacer eso, agregue uno más uno más a su respuesta y omita el resto de esto.
Una vez que comience a ejecutar cosas fuera de la nube, o tenga un tipo diferente de secreto, hay dos lugares clave que recomiendo no almacenar secretos:
Variables de entorno: cuando se definen en un contenedor, cada proceso dentro del contenedor tiene acceso a ellas, son visibles a través de /proc, las aplicaciones pueden volcar su entorno a la salida estándar donde se almacena en los registros y, lo que es más importante, aparecen en texto claro cuando inspeccione el contenedor.
En la imagen en sí: las imágenes a menudo se envían a los registros donde muchos usuarios tienen acceso de extracción, a veces sin necesidad de credenciales para extraer la imagen. Incluso si elimina el secreto de una capa, la imagen se puede desarmar con utilidades comunes de Linux como tar y el secreto se puede encontrar desde el paso donde se agregó por primera vez a la imagen.
Entonces, ¿qué otras opciones hay para los secretos en los contenedores Docker?
Opción A: si necesita este secreto solo durante la compilación de su imagen, no puede usar el secreto antes de que comience la compilación y aún no tiene acceso a BuildKit, entonces una compilación de varias etapas es la mejor de las malas opciones. Agregaría el secreto a las etapas iniciales de la compilación, lo usaría allí y luego copiaría la salida de esa etapa sin el secreto a su etapa de lanzamiento, y solo enviaría esa etapa de lanzamiento a los servidores de registro. Este secreto todavía está en la caché de imágenes en el servidor de compilación, por lo que tiendo a usarlo solo como último recurso.
Opción B: también durante el tiempo de compilación, si puede usar BuildKit que se lanzó en 18.09, actualmente hay funciones experimentales que permiten la inyección de secretos como un montaje de volumen para una sola línea RUN. Ese montaje no se escribe en las capas de la imagen, por lo que puede acceder al secreto durante la compilación sin preocuparse de que se envíe a un servidor de registro público. El Dockerfile resultante se ve así:
# syntax = docker/dockerfile:experimental FROM python:3 RUN pip install awscli RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...Y lo creas con un comando en 18.09 o posterior como:
DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .Opción C: en tiempo de ejecución en un solo nodo, sin modo Swarm u otra orquestación, puede montar las credenciales como un volumen de solo lectura. El acceso a esta credencial requiere el mismo acceso que tendría fuera de Docker al mismo archivo de credenciales, por lo que no es mejor ni peor que el escenario sin Docker. Lo que es más importante, el contenido de este archivo no debería estar visible cuando inspeccione el contenedor, vea los registros o envíe la imagen a un servidor de registro, ya que el volumen está fuera de eso en todos los escenarios. Esto requiere que copie sus credenciales en el host de la ventana acoplable, aparte de la implementación del contenedor. (Tenga en cuenta que cualquier persona con la capacidad de ejecutar contenedores en ese host puede ver su credencial, ya que el acceso a la API de docker es raíz en el host y la raíz puede ver los archivos de cualquier usuario. Si no confía en los usuarios con raíz en el host , entonces no les dé acceso a la API de la ventana acoplable).
Para una docker run , esto se ve así:
docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_imageO para un archivo de redacción, tendrías:
version: '3' services: app: image: your_image volumes: - $HOME/.aws/credentials:/home/app/.aws/credentials:roOpción D: con herramientas de orquestación como Swarm Mode y Kubernetes, ahora tenemos compatibilidad con secretos que es mejor que un volumen. Con el modo Swarm, el archivo se cifra en el sistema de archivos del administrador (aunque la clave de descifrado a menudo también está allí, lo que permite reiniciar el administrador sin que un administrador ingrese una clave de descifrado). Más importante aún, el secreto solo se envía a los trabajadores que necesitan el secreto (ejecutando un contenedor con ese secreto), solo se almacena en la memoria del trabajador, nunca en el disco, y se inyecta como un archivo en el contenedor con un tmpfs montar. Los usuarios en el host fuera del enjambre no pueden montar ese secreto directamente en su propio contenedor; sin embargo, con acceso abierto a la API de la ventana acoplable, podrían extraer el secreto de un contenedor en ejecución en el nodo, así que, de nuevo, limite quién tiene este acceso al API. De componer, esta inyección secreta se parece a:
version: '3.7' secrets: aws_creds: external: true services: app: image: your_image secrets: - source: aws_creds target: /home/user/.aws/credentials uid: '1000' gid: '1000' mode: 0700 Activa el modo de enjambre con docker swarm init para un solo nodo y luego sigue las instrucciones para agregar nodos adicionales. Puede crear el secreto de forma externa con docker secret create aws_creds $HOME/.aws/credentials . E implementa el archivo de redacción con docker stack deploy -c docker-compose.yml stack_name .
A menudo versiono mis secretos usando un script de: https://github.com/sudo-bmitch/docker-config-update
Opción E: existen otras herramientas para administrar secretos, y mi favorita es Vault porque brinda la capacidad de crear secretos por tiempo limitado que caducan automáticamente. Luego, cada aplicación obtiene su propio conjunto de tokens para solicitar secretos, y esos tokens les dan la capacidad de solicitar esos secretos de tiempo limitado mientras puedan llegar al servidor de la bóveda. Eso reduce el riesgo si alguna vez se elimina un secreto de su red, ya que no funcionará o caducará rápidamente. La funcionalidad específica de AWS para Vault está documentada en https://www.vaultproject.io/docs/secrets/aws/index.html
La mejor manera es utilizar el rol de IAM y no ocuparse de las credenciales en absoluto. (consulte http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )
Las credenciales se pueden recuperar desde http://169.254.169.254..... Dado que se trata de una dirección IP privada, solo se puede acceder a ella desde instancias EC2.
Todas las bibliotecas de clientes de AWS modernas "saben" cómo obtener, actualizar y usar credenciales desde allí. Entonces, en la mayoría de los casos, ni siquiera necesita saberlo. Simplemente ejecute ec2 con el rol de IAM correcto y listo.
Como opción, puede pasarlos en tiempo de ejecución como variables de entorno (es decir docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage )
Puede acceder a estas variables de entorno ejecutando printenv en la terminal.
La siguiente línea me funciona incluso cuando mis credenciales están configuradas por aws-okta o saml2aws :
$ docker run -v$HOME/.aws:/root/.aws:ro \ -e AWS_ACCESS_KEY_ID \ -e AWS_CA_BUNDLE \ -e AWS_CLI_FILE_ENCODING \ -e AWS_CONFIG_FILE \ -e AWS_DEFAULT_OUTPUT \ -e AWS_DEFAULT_REGION \ -e AWS_PAGER \ -e AWS_PROFILE \ -e AWS_ROLE_SESSION_NAME \ -e AWS_SECRET_ACCESS_KEY \ -e AWS_SESSION_TOKEN \ -e AWS_SHARED_CREDENTIALS_FILE \ -e AWS_STS_REGIONAL_ENDPOINTS \ amazon/aws-cli s3 ls Tenga en cuenta que para casos de uso avanzado, es posible que deba permitir permisos rw (lectura y escritura), así que omita la limitación ro (solo lectura) al montar el volumen .aws en -v$HOME/.aws:/root/.aws:ro
Podría crear ~/aws_env_creds que contenga:
touch ~/aws_env_creds chmod 777 ~/aws_env_creds vi ~/aws_env_credsAgregue estos valores (reemplace la clave suya):
AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2CPresione "esc" para guardar el archivo.
Ejecute y pruebe el contenedor:
my_service: build: . image: my_image env_file: - ~/aws_env_credsSi alguien aún enfrenta el mismo problema después de seguir las instrucciones mencionadas en la respuesta aceptada, asegúrese de no pasar variables de entorno de dos fuentes diferentes. En mi caso, estaba pasando variables de entorno a la docker run a través de un archivo y como parámetros que causaban que las variables pasadas como parámetros no mostraran ningún efecto.
Así que el siguiente comando no funcionó para mí:
docker run --env-file ./env.list -e AWS_ACCESS_KEY_ID=ABCD -e AWS_SECRET_ACCESS_KEY=PQRST IMAGE_NAME:v1.0.1 Mover las credenciales de aws al archivo env.list mencionado ayudó.
El montaje de volumen se indica en este hilo, pero a partir de docker-compose v3.2 + puede vincular el montaje.
Por ejemplo, si tiene un archivo llamado .aws_creds en la raíz de su proyecto:
En su servicio para el archivo de composición, haga esto para los volúmenes:
volumes: # normal volume mount, already shown in thread - ./.aws_creds:/root/.aws/credentials # way 2, note this requires docker-compose v 3.2+ - type: bind source: .aws_creds # from local target: /root/.aws/credentials # to the container location Con esta idea, puede almacenar públicamente sus imágenes acoplables en docker-hub porque sus aws credentials no estarán físicamente en la imagen... para tenerlas asociadas, debe tener la estructura de directorio correcta localmente donde se inicia el contenedor (es decir, extraer de Git)
Basado en algunas de las respuestas anteriores, construí la mía de la siguiente manera. La estructura de mi proyecto:
├── Dockerfile ├── code │ └── main.py ├── credentials ├── docker-compose.yml └── requirements.txt Mi archivo docker-compose.yml :
version: "3" services: app: build: context: . volumes: - ./credentials:/root/.aws/credentials - ./code:/home/app Mi archivo Docker :
FROM python:3.8-alpine RUN pip3 --no-cache-dir install --upgrade awscli RUN mkdir /app WORKDIR /home/app CMD python main.py