¿Cómo usar sudo dentro de un contenedor acoplable?

259

Normalmente, los contenedores Docker se ejecutan utilizando la raíz del usuario . Me gustaría usar un usuario diferente, lo cual no es un problema usando la directiva USER de docker. Pero este usuario debería poder usar sudo dentro del contenedor. Este comando falta.

Aquí hay un Dockerfile simple para este propósito:

FROM ubuntu:12.04

RUN useradd docker && echo "docker:docker" | chpasswd
RUN mkdir -p /home/docker && chown -R docker:docker /home/docker

USER docker
CMD /bin/bash

Al ejecutar este contenedor, me conecto con el usuario 'docker'. Cuando intento usar sudo, no se encuentra el comando. Así que intenté instalar el paquete sudo dentro de mi Dockerfile usando

RUN apt-get install sudo

Esto resulta en No se puede localizar el paquete sudo

drubb
fuente
Solo dale sudo group al usuario. askubuntu.com/questions/7477/…
Regan

Respuestas:

242

Acabo de recibirlo. Como señaló Regan, tuve que agregar al usuario al grupo de sudoers. Pero la razón principal fue que olvidé actualizar el caché de repositorios, por lo que apt-get no pudo encontrar el paquete sudo. Está funcionando ahora. Aquí está el código completo:

FROM ubuntu:12.04

RUN apt-get update && \
      apt-get -y install sudo

RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo

USER docker
CMD /bin/bash
drubb
fuente
8
No funciona en centos. el addusercomando escupe la ayuda de uso parauseradd
Emad
Para CentOS, puede agregar un usuario y un grupo, luego crear un archivo de fragmento /etc/sudoers.d/y establecer los permisos 440en ese archivo. Entonces el usuario tendría acceso a sudo en CentOS, 6 y superior. 5 tendrá que agregar la #includedir /etc/sudoers.ddirectiva en/etc/sudoers
FilBot3
No funciona para mi Tengo esos errores: E: No se pudo abrir el archivo de bloqueo / var / lib / apt / lists / lock - open (13: Permiso denegado) E: No se puede bloquear el directorio / var / lib / apt / lists /
Marosinho
1
Esto no parece funcionar para la imagen acoplable Ubuntu 18.04
viggy
100

Cuando ni sudo ni apt-get están disponibles en el contenedor, también puede saltar al contenedor en ejecución como usuario root utilizando el comando

docker exec -u root -t -i container_id /bin/bash
Tomáš Záluský
fuente
Esta es una solución mucho mejor a lo que el OP probablemente quiere lograr, a pesar de que la respuesta aceptada da la solución solicitada. ¡Por lo menos, es la respuesta que estaba buscando!
spikyjt
79

Las otras respuestas no me funcionaron. Seguí buscando y encontré una publicación de blog que cubría cómo un equipo estaba ejecutando no root dentro de un contenedor acoplable.

Aquí está la versión TL; DR:

RUN apt-get update \
 && apt-get install -y sudo

RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

USER docker

# this is where I was running into problems with the other approaches
RUN sudo apt-get update 

Estaba usando FROM node:9.3esto, pero sospecho que otras bases de contenedores similares también funcionarían.

M. Scott Ford
fuente
Estoy usando ubuntu:bionic-20180724.1. Usé este enfoque pero, después de lo anterior, no me permite instalar otro paquete. Me adjuntas una línea a lo anterior Dockerfilecon el fin de instalar un paquete con: RUN apt-get install -y tree. Sin embargo, me dio este mensaje de error:Step xxxx/xxxx : RUN apt-get install -y tree ---> Running in j5e6gsvwfafa Reading package lists... E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/
edesz
1
@WR Creo que necesitas cambiar esa línea para leer RUN sudo apt-get install -y tree. Después de configurarlo USERen algo diferente root, deberá usar sudocualquier comando que requiera rootprivilegios.
M. Scott Ford
¡Ah gracias! Me perdí eso. No pensé que sudofuera permitido en un Dockerfile.
edesz
Perfecto, justo lo que necesitaba.
Arin Ekandem
25

Para cualquiera que tenga este problema con un contenedor que ya se está ejecutando, y no necesariamente quiere reconstruir, el siguiente comando se conecta a un contenedor en ejecución con privilegios de root:

docker exec -ti -u root container_name bash

También puede conectarse usando su ID, en lugar de su nombre, al encontrarlo con:

docker ps -l

Para guardar sus cambios para que sigan allí la próxima vez que inicie el contenedor (o el clúster docker-compose):

docker commit container_id image_name

Para iniciar un contenedor que no se está ejecutando y conectarse como root:

docker run -ti -u root --entrypoint=/bin/bash image_id_or_name -s

Para copiar desde un contenedor en ejecución:

docker cp <containerId>:/file/path/within/container /host/path/target

Para exportar una copia de la imagen:

docker save container | gzip > /dir/file.tar.gz

Que puede restaurar a otra instalación de Docker usando:

gzcat /dir/file.tar.gz | docker load

Es mucho más rápido pero toma más espacio para no comprimir, usando:

docker save container | dir/file.tar

Y:

cat dir/file.tar | docker load
Chris
fuente
17

si quieres conectarte al contenedor e instalar algo
usando apt-get
primero como la respuesta anterior de nuestro hermano "Tomáš Záluský"

docker exec -u root -t -i container_id /bin/bash

entonces trata de

EJECUTAR apt-get update o apt-get 'lo que quieras'

funcionó conmigo espero que sea útil para todos

Ismail
fuente
5

Si no se puede acceder a SUDO o apt-get dentro del Contenedor, puede usar la siguiente opción en el contenedor en ejecución.

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" es mi ID de contenedor y aquí está el ejemplo de trabajo de mi terminal:

ingrese la descripción de la imagen aquí

Yogi Ghorecha
fuente
3

Así es como configuro un usuario no root con la imagen base de ubuntu:18.04:

RUN \
    groupadd -g 999 foo && useradd -u 999 -g foo -G sudo -m -s /bin/bash foo && \
    sed -i /etc/sudoers -re 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^root.*/root ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^#includedir.*/## **Removed the include directive** ##"/g' && \
    echo "foo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "Customized the sudoers file for passwordless access to the foo user!" && \
    echo "foo user:";  su - foo -c id

Qué sucede con el código anterior:

  • Se foocrea el usuario y el grupo .
  • El usuario foose añade a la tanto la fooy sudogrupo.
  • El uidy gidse establece en el valor de 999.
  • El directorio de inicio está establecido en /home/foo.
  • El shell está configurado en /bin/bash.
  • El sedcomando no hace actualizaciones en línea para el /etc/sudoersarchivo para permitir fooy rootusuarios sin contraseña de acceso al sudogrupo.
  • El sedcomando deshabilita la #includedirdirectiva que permitiría que cualquier archivo en subdirectorios anule estas actualizaciones en línea.
Seth Bergman
fuente
2

Si tiene un contenedor ejecutándose como root que ejecuta un script (que no puede cambiar) que necesita acceso al sudocomando, simplemente puede crear un nuevo sudoscript en su $PATHque llame al comando pasado.

Por ejemplo, en su Dockerfile:

RUN if type sudo 2>/dev/null; then \ 
     echo "The sudo command already exists... Skipping."; \
    else \
     echo -e "#!/bin/sh\n\${@}" > /usr/sbin/sudo; \
     chmod +x /usr/sbin/sudo; \
    fi
XtraSimplicity
fuente
1
Dependiendo de las imágenes de la ventana acoplable que esté utilizando (en mi caso Ubuntu: 18.04), es posible que deba eliminar el -earchivo echo. De lo contrario, estará presente en el archivo en sí mismo, haciéndolo infuncional.
stiller_leser
Buena idea, pero esto no funcionará si el comando original está usando opciones de sudo, como sudo -E ls. Intentará ejecutarlo -E ls.
wisbucky
2

Es posible que esto no funcione para todas las imágenes, pero algunas imágenes ya contienen un usuario raíz, como en la imagen jupyterhub / singleuser. Con esa imagen es simplemente:

USER root
RUN sudo apt-get update
Alex Kaszynski
fuente
1

Usa Alias.

alias sudo=''

Simple pero eficiente. No olvide agregarlo a ~ / .bash_aliases para que funcione después de abrir un nuevo shell.

nano ~/.bash_aliases
alias sudo=''
#(Ctrl+X)

Dado que el usuario es la raíz predeterminada en Docker, 'ignorar' el comando sudo es la forma más fácil.

Dogkiller87
fuente
0

A diferencia de la respuesta aceptada , yo uso usermoden su lugar.

Suponga que ya inició sesión como root en Docker, y "fruit" es el nuevo nombre de usuario no root que quiero agregar, simplemente ejecute estos comandos:

apt update && apt install sudo
adduser fruit
usermod -aG sudo fruit

Recuerde guardar la imagen después de la actualización. Utilícelo docker pspara obtener la <ID DE CONTENEDOR> y <IMAGEN> de la ventana acoplable en ejecución actual, luego ejecute docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>para guardar la imagen de la ventana acoplable.

Luego prueba con:

su fruit
sudo whoami

O pruebe mediante inicio de sesión directo (asegúrese de guardar la imagen primero) como ese usuario no root cuando inicie la ventana acoplable:

docker run -it --user fruit <IMAGE>
sudo whoami

Puede usar sudo -kpara restablecer la marca de tiempo de solicitud de contraseña:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password
Fruta
fuente