Tengo una aplicación que ejecuta varias cosas divertidas con Git (como ejecutar git clone y git push) y estoy tratando de acoplarlo.
Sin embargo, me encuentro con un problema en el que necesito poder agregar una clave SSH al contenedor para que lo use el 'usuario' del contenedor.
Traté de copiarlo /root/.ssh/
, cambiando$HOME
, crear un git ssh wrapper, y aún así no suerte.
Aquí está el Dockerfile para referencia:
#DOCKER-VERSION 0.3.4
from ubuntu:12.04
RUN apt-get update
RUN apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install nodejs -y
ADD . /src
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
RUN cd /src; npm install
EXPOSE 808:808
CMD [ "node", "/src/app.js"]
app.js
ejecuta los comandos git como git pull
Respuestas:
Es un problema más difícil si necesita usar SSH en el momento de la compilación. Por ejemplo, si está utilizando
git clone
, o en mi casopip
ynpm
para descargar desde un repositorio privado.La solución que encontré es agregar tus claves usando la
--build-arg
bandera. Luego puede usar el nuevo--squash
comando experimental (agregado 1.13) para fusionar las capas para que las claves ya no estén disponibles después de la eliminación. Aquí está mi solución:Comando de compilación
Dockerfile
Actualización: si está utilizando Docker 1.13 y tiene características experimentales, puede agregar
--squash
el comando de compilación que fusionará las capas, eliminará las claves SSH y las ocultarádocker history
.fuente
id_rsa.pub
archivo, ya que no es necesario.$(openssl rsa -in ~/.ssh/id_rsa)
en su lugarResulta que cuando se usa Ubuntu, el ssh_config no es correcto. Necesitas agregar
a su Dockerfile para que reconozca su clave ssh.
fuente
RUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
La clave ssh permanece almacenada dentro de la imagen, incluso si elimina la clave en un comando de capa después de agregarla (vea los comentarios en esta publicación ).
En mi caso, esto está bien, así que esto es lo que estoy usando:
fuente
Si está utilizando docker compose, una opción fácil es reenviar el agente SSH así:
fuente
SSH_AUTH_SOCK
es una variable que contiene una ruta a un agente sshSSH_AUTH_SOCK
blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add$SSH_AUTH_SOCK
, debe montar esta ruta/run/host-services/ssh-auth.sock
.Ampliando la respuesta de Peter Grainger Pude usar la construcción en varias etapas disponible desde Docker 17.05. La página oficial dice:
Tener esto en cuenta aquí es mi ejemplo de
Dockerfile
incluir tres etapas de construcción. Está destinado a crear una imagen de producción de la aplicación web del cliente..dockerignore
repite el contenido del.gitignore
archivo (evitanode_modules
ydist
se copian los directorios resultantes del proyecto):Ejemplo de comando para construir una imagen:
Si su clave SSH privada no tiene una frase de contraseña, especifique un
SSH_KEY_PASSPHRASE
argumento vacío .Así es como funciona:
1) Solo en la primera etapa
package.json
, losyarn.lock
archivos y la clave SSH privada se copian en la primera imagen intermedia nombradasources
. Para evitar más mensajes de frase clave de SSH, se agrega automáticamente assh-agent
. Finalmente, elyarn
comando instala todas las dependencias requeridas de NPM y clona repositorios privados de git de Bitbucket sobre SSH.2) La segunda etapa construye y minimiza el código fuente de la aplicación web y lo coloca en el
dist
directorio de la siguiente imagen intermedia nombradaproduction
. Tenga en cuenta que el código fuente de instaladonode_modules
se copia de la imagen nombradasources
producida en la primera etapa por esta línea:Probablemente también podría ser la siguiente línea:
Sólo tenemos
node_modules
directorio de la primera imagen intermedia, noSSH_KEY
ySSH_KEY_PASSPHRASE
argumentos. Todo el resto requerido para la compilación se copia de nuestro directorio de proyectos.3) En la tercera etapa, reducimos el tamaño de la imagen final que se etiquetará
ezze/geoport:0.6.0
al incluir solodist
directorio de la segunda imagen intermedia nombradaproduction
e instalar Node Express para iniciar un servidor web.Listado de imágenes da una salida como esta:
donde las imágenes no etiquetadas corresponden a la primera y la segunda etapa de construcción intermedia.
Si tu corres
no verá ninguna mención de
SSH_KEY
ySSH_KEY_PASSPHRASE
en la imagen final.fuente
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
pero cuando registro otro RUN o incluso en el mismo RUN al hacer un comandossh-add -l
me dice que "El agente no tiene identidades". Empezando a arrancarme el pelo, ¿alguna idea?Para inyectar su clave ssh, dentro de un contenedor, tiene múltiples soluciones:
Usando un Dockerfile con las
ADD
instrucciones, puede inyectarlo durante su proceso de compilaciónSimplemente haciendo algo como
cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'
Usando el
docker cp
comando que le permite inyectar archivos mientras se está ejecutando un contenedor.fuente
apt-get install openssh-server
y poniendo mi clave en /root/.ssh/id_rsa y funcionó bien. ¿Qué imagen estás usando?Una solución multiplataforma es usar un montaje de enlace para compartir la
.ssh
carpeta del host con el contenedor:Similar al reenvío de agentes, este enfoque hará que las claves públicas sean accesibles para el contenedor. Una ventaja adicional es que también funciona con un usuario no root y lo conectará a GitHub. Sin embargo, una advertencia a tener en cuenta es que todos los contenidos (incluidas las claves privadas) de la
.ssh
carpeta se compartirán, por lo que este enfoque solo es deseable para el desarrollo y solo para imágenes de contenedor confiables.fuente
docker build
solo durantedocker run
docker-compose up
en mi Windows 10. local ¿Cómo debo usar su solución en ese escenario?Los contenedores Docker deben verse como "servicios" propios. Para separar las preocupaciones, debe separar las funcionalidades:
1) Los datos deben estar en un contenedor de datos: use un volumen vinculado para clonar el repositorio. Ese contenedor de datos se puede vincular al servicio que lo necesita.
2) Use un contenedor para ejecutar la tarea de clonación git (es decir, su único trabajo es la clonación) vinculando el contenedor de datos cuando la ejecute.
3) Lo mismo para la clave ssh: póngalo como un volumen (como se sugirió anteriormente) y vincúlelo al servicio git clone cuando lo necesite
De esa manera, tanto la tarea de clonación como la clave son efímeras y solo están activas cuando es necesario.
Ahora, si su aplicación en sí es una interfaz git, es posible que desee considerar las API REST de github o bitbucket directamente para hacer su trabajo: para eso están diseñadas.
fuente
Esta línea es un problema:
Al especificar los archivos que desea copiar en la imagen, solo puede usar rutas relativas, relativas al directorio donde está su Dockerfile. Entonces deberías usar:
Y coloque el archivo id_rsa en el mismo directorio donde está su Dockerfile.
Mira esto para más detalles: http://docs.docker.io/reference/builder/#add
fuente
docker cp
solo lo pone en el contenedor y no en la imagen, ¿verdad?Tuvimos un problema similar al hacer la instalación de npm en el tiempo de compilación de Docker.
Inspirado en la solución de Daniel van Flymen y combinándola con git url rewrite , encontramos un método un poco más simple para autenticar la instalación de npm desde repositorios privados de github: utilizamos tokens oauth2 en lugar de las claves.
En nuestro caso, las dependencias npm se especificaron como "git + https://github.com/ ..."
Para la autenticación en el contenedor, las URL deben reescribirse para que sean adecuadas para la autenticación ssh (ssh: //[email protected]/) o la autenticación de token (https: // $ {GITHUB_TOKEN} @ github.com /)
Comando de compilación:
Desafortunadamente, estoy en Docker 1.9, por lo que la opción de squash aún no está disponible, eventualmente debe agregarse
Dockerfile:
fuente
Reenvíe el socket de autenticación ssh al contenedor:
Su guión podrá realizar a
git clone
.Extra: si desea que los archivos clonados pertenezcan a un usuario específico, debe usarlos,
chown
ya que usar otro usuario que no sea root dentro del contenedor hará quegit
falle.Puede hacer esto publicando en el entorno del contenedor algunas variables adicionales:
Después de clonar, debe ejecutar
chown $OWNER_USER:$OWNER_GROUP -R <source_folder>
para establecer la propiedad adecuada antes de abandonar el contenedor para que un usuario no root pueda acceder a los archivos fuera del contenedor.fuente
-u root:$(id -u $USER)
para tener al menos los archivos propiedad del mismo grupo primario que su usuario, lo que debería hacer que todos sean al menos legibles, asudo
menos que algo los esté creando con0600
permisos.-u root:$(id -u $USER)
debería serlo-g
./tmp/ssh_auth.sock: No such file or directory
que está/tmp/ssh-vid8Zzi8UILE/agent.46016
en mi máquina host/tmp
dentro de su contenedor. O un error tipográfico en el comando Docker Run. Asegúrese de que la declaración de enlace sea correcta-v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock
: el orden es importante y el punto y coma también es importante. Consulte la documentación de la ventana acoplable para obtener más ayuda.Como ya comentó eczajk en la respuesta de Daniel van Flymen, no parece seguro quitar las llaves y usarlas
--squash
, ya que aún serán visibles en el historial (docker history --no-trunc
).En cambio, con Docker 18.09, ahora puede usar la función "construir secretos". En mi caso, cloné un repositorio privado de git usando la clave SSH de mi host con lo siguiente en mi Dockerfile:
Para poder usar esto, debe habilitar el nuevo backend BuildKit antes de ejecutar
docker build
:Y necesitas agregar el
--ssh default
parámetro adocker build
.Más información sobre esto aquí: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
fuente
ssh-add ~/.ssh/id_rsa
y 2) agregar el host git a known_hosts, es decir, para bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.
esto a pesar de pasar la--ssh default
bandera en mi Docker Build y usar--mount=type=ssh
el comando de ejecución donde yogit clone
. Puedo clonar el mismo repositorio sin problemas en la máquina de compilación. Simplemente falla en el contenedor de compilación de la ventana acoplable. Sospecho que la versión mac de Docker no está pasando el cliente ssh.Este problema es realmente molesto. Dado que no puede agregar / copiar ningún archivo fuera del contexto de dockerfile, lo que significa que es imposible vincular ~ / .ssh / id_rsa en /root/.ssh/id_rsa de la imagen, y cuando definitivamente necesita una clave para hacer algo como git clone desde un enlace de repositorio privado ..., durante la construcción de su imagen acoplable.
De todos modos, encontré una solución alternativa, no tan convincente, pero funcionó para mí.
en su dockerfile:
Un guión para hacer en una sesión:
cada vez que tenga que ejecutar un contenedor desde esta imagen con algunos requisitos ssh, simplemente agregue -v para el comando de ejecución, como:
docker run -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa --name comando de imagen de contenedor
Esta solución da como resultado que no haya una clave privada tanto en la fuente del proyecto como en la imagen incorporada del acoplador, por lo que ya no debe preocuparse por ningún problema de seguridad.
fuente
docker cp
? Se utiliza para "Copiar archivos / carpetas entre un contenedor y su host".docker cp
podría hacer el truco. Sin embargo, en esta misma situación, necesitaba el ssh_key durante la construcción de la imagen, y no hay ningún contenedor en ese momento ... actualizará mi expresión poco clara, gracias de todos modos.Me encontré con el mismo problema hoy y la versión un poco modificada con publicaciones anteriores me pareció más útil para mí.
(Tenga en cuenta que solo marca para que el contenedor no ensucie mi clave ssh en ningún caso).
Dentro del contenedor ahora puedo ejecutar:
Así que no recibo ese
Bad owner or permissions on /root/.ssh/..
error que notó @krossfuente
ssh-agent bash -c "ssh-add..."
. Entonces puedo pasar eso directamente a Docker Run. Todos los ejemplos anteriores que encontré utilizadoseval ssh-agent
, seguidos de ssh-add y no pude encontrar una manera de pasar eso aeval
través del comando docker run.'puede permitir selectivamente que los servidores remotos accedan a su agente ssh local como si se estuviera ejecutando en el servidor'
https://developer.github.com/guides/using-ssh-agent-forwarding/
fuente
También puede vincular su directorio .ssh entre el host y el contenedor, no sé si este método tiene alguna implicación de seguridad, pero puede ser el método más fácil. Algo como esto debería funcionar:
Recuerde que Docker se ejecuta con sudo (a menos que no lo haga), si este es el caso, usará las claves ssh raíz.
fuente
Bad owner or permissions on /root/.ssh/config
.docker run
, pero no durantedocker build
.A partir de
docker API 1.39+
(Verifique la versión de API condocker version
),--ssh
Docker Build permite la opción con un socket de agente o claves para permitir que Docker Engine reenvíe las conexiones de agente SSH.Comando de construcción
Dockerfile
Más información:
fuente
could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory
. Use la ruta completa si no funciona.Si no le importa la seguridad de sus claves SSH, aquí hay muchas buenas respuestas. Si lo hace, la mejor respuesta que encontré fue de un enlace en un comentario anterior a este comentario de GitHub por diegocsandrim . Para que otros tengan más probabilidades de verlo, y en caso de que ese repositorio desaparezca, aquí hay una versión editada de esa respuesta:
La mayoría de las soluciones aquí terminan dejando la clave privada en la imagen. Esto es malo, ya que cualquier persona con acceso a la imagen tiene acceso a su clave privada. Como no sabemos lo suficiente sobre el comportamiento de
squash
, este puede ser el caso incluso si elimina la clave y aplasta esa capa.Generamos una URL de pre-firma para acceder a la clave con aws s3 cli, y limitamos el acceso durante aproximadamente 5 minutos, guardamos esta URL de pre-firma en un archivo en el directorio repo, luego en dockerfile la agregamos a la imagen.
En dockerfile tenemos un comando EJECUTAR que realiza todos estos pasos: use la URL previa al canto para obtener la clave ssh, ejecute npm install y elimine la clave ssh.
Al hacer esto en un solo comando, la clave ssh no se almacenaría en ninguna capa, pero la URL de pre-firma se almacenará, y esto no es un problema porque la URL no será válida después de 5 minutos.
El script de compilación se ve así:
Dockerfile se ve así:
fuente
En versiones posteriores de docker (17.05) puede usar compilaciones de varias etapas . Cuál es la opción más segura ya que las construcciones anteriores solo pueden ser utilizadas por la construcción posterior y luego se destruyen
Consulte la respuesta a mi pregunta de stackoverflow para obtener más información.
fuente
Aquí se detalla una descripción concisa de los desafíos de SSH dentro de los contenedores Docker . Para conectarse a controles remotos confiables desde un contenedor sin filtrar secretos, hay algunas maneras:
~/.ssh
al contenedor. (Solo desarrollo, potencialmente inseguro)Más allá de estos, también existe la posibilidad de usar un almacén de claves que se ejecuta en un contenedor acoplado separado accesible en tiempo de ejecución cuando se usa Compose. El inconveniente aquí es la complejidad adicional debido a la maquinaria requerida para crear y administrar un almacén de claves como Vault by HashiCorp .
Para el uso de la clave SSH en un contenedor Docker independiente, consulte los métodos vinculados anteriormente y considere los inconvenientes de cada uno según sus necesidades específicas. Sin embargo, si está ejecutando dentro de Compose y desea compartir una clave para una aplicación en tiempo de ejecución (que refleja los aspectos prácticos del OP) intente esto:
docker-compose.env
archivo y agréguelo a su.gitignore
archivo.docker-compose.yml
y agregueenv_file
para el servicio que requiere la clave.process.node.DEPLOYER_RSA_PUBKEY
en el caso de una aplicación Node.js.El enfoque anterior es ideal para el desarrollo y las pruebas y, si bien podría satisfacer los requisitos de producción, en la producción es mejor usar uno de los otros métodos identificados anteriormente.
Recursos adicionales:
fuente
Puede usar la compilación de varias etapas para compilar contenedores. Este es el enfoque que puede tomar:
Etapa 1 construyendo una imagen con ssh
Etapa 2: construye tu contenedor
agregue el atributo env en su archivo de redacción:
luego pasa los argumentos del script de construcción de esta manera:
Y retire el contenedor intermedio por seguridad. Esto te ayudará a aplaudir.
fuente
Una forma simple y segura de lograr esto sin guardar su clave en una capa de imagen de Docker o pasar por la gimnasia ssh_agent es:
Como uno de los pasos en su
Dockerfile
, cree un.ssh
directorio agregando:RUN mkdir -p /root/.ssh
A continuación, eso indica que le gustaría montar el directorio ssh como un volumen:
VOLUME [ "/root/.ssh" ]
Asegúrese de que su contenedor
ssh_config
sepa dónde encontrar las claves públicas agregando esta línea:RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
Exponga el
.ssh
directorio del usuario local al contenedor en tiempo de ejecución:docker run -v ~/.ssh:/root/.ssh -it image_name
O
dockerCompose.yml
agregue esto debajo de la tecla de volumen del servicio:- "~/.ssh:/root/.ssh"
Su final
Dockerfile
debe contener algo como:fuente
Estoy tratando de resolver el problema de otra manera: agregando clave ssh pública a una imagen. Pero en mis pruebas, descubrí que "docker cp" es para copiar DE un contenedor a un host. El ítem 3 en la respuesta de crujido parece estar diciendo que puede usar docker cp para inyectar archivos en un contenedor. Ver https://docs.docker.com/engine/reference/commandline/cp/
extracto
fuente
Puede pasar las claves autorizadas a su contenedor utilizando una carpeta compartida y establecer permisos utilizando un archivo acoplable como este:
Y la ejecución de la ventana acoplable contiene algo como lo siguiente para compartir un directorio de autenticación en el host (que contiene las claves autorizadas) con el contenedor y luego abrir el puerto ssh que será accesible a través del puerto 7001 en el host.
Es posible que desee ver https://github.com/jpetazzo/nsenter, que parece ser otra forma de abrir un shell en un contenedor y ejecutar comandos dentro de un contenedor.
fuente
Tarde para la fiesta, sin duda, ¿qué tal esto que hará que las claves de su sistema operativo host estén disponibles para rootear dentro del contenedor, sobre la marcha:
No estoy a favor de usar Dockerfile para instalar claves, ya que las iteraciones de su contenedor pueden dejar claves privadas.
fuente
Estaba tratando de descubrir cómo agregar claves de firma a un contenedor para usar durante el tiempo de ejecución (no compilar) y me encontré con esta pregunta. Los secretos de Docker parecen ser la solución para mi caso de uso, y como todavía nadie lo ha mencionado, lo agregaré.
fuente
En mi caso tuve un problema con nodejs y 'npm i' desde un repositorio remoto. Lo arreglé, agregó el usuario 'node' al contenedor de nodejs y 700 a ~ / .ssh en el contenedor.
Dockerfile:
run.sh:
docker-compose.yml:
después de eso comenzó a funcionar
fuente
De la manera más simple, obtenga una cuenta de launchpad y use: ssh-import-id
fuente
ssh-import-id
parece que solo importa claves públicas.En un contenedor Docker en ejecución, puede emitir ssh-keygen con la opción docker -i (interactiva). Esto reenviará las indicaciones del contenedor para crear la clave dentro del contenedor acoplable.
fuente
Para debian / root / Authorized_keys:
fuente