Come usare sudo all'interno di un contenitore docker?


259

Normalmente, i contenitori docker vengono eseguiti utilizzando l'utente root . Vorrei usare un altro utente, il che non è un problema usando la direttiva USER della docker. Ma questo utente dovrebbe essere in grado di usare sudo all'interno del contenitore. Questo comando è mancante.

Ecco un semplice file Docker per questo scopo:

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

Eseguendo questo contenitore, ottengo l'accesso con l'utente 'docker'. Quando provo ad usare sudo, il comando non viene trovato. Quindi ho provato a installare il pacchetto sudo nel mio Dockerfile usando

RUN apt-get install sudo

Ciò comporta Impossibile trovare il pacchetto sudo


Basta dare il gruppo sudo all'utente. askubuntu.com/questions/7477/…
Regan,

Risposte:


242

Ho appena capito. Come ha sottolineato regan, ho dovuto aggiungere l'utente al gruppo sudoers. Ma il motivo principale era che avevo dimenticato di aggiornare la cache dei repository, quindi apt-get non è riuscito a trovare il pacchetto sudo. Sta lavorando adesso. Ecco il codice 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

8
non funziona in centos. il addusercomando sputa l'aiuto per l'usouseradd
Emad

Per CentOS, è possibile aggiungere un utente e un gruppo, quindi creare un file shard in /etc/sudoers.d/e impostare le autorizzazioni 440su quel file. Quindi l'utente avrebbe accesso sudo in CentOS, 6 e versioni successive. 5 dovrai aggiungere la #includedir /etc/sudoers.ddirettiva in/etc/sudoers
FilBot3

Non funziona per me. Ho questi errori: E: Impossibile aprire il file di blocco / var / lib / apt / lists / lock - open (13: autorizzazione negata) E: Impossibile bloccare la directory / var / lib / apt / lists /
Marosinho

1
Questo sembra non funzionare per l'immagine
docker di

100

Quando né sudo né apt-get sono disponibili nel contenitore, è anche possibile passare al contenitore in esecuzione come utente root utilizzando il comando

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

Questa è una soluzione molto migliore a ciò che l'OP probabilmente vuole ottenere, anche se la risposta accettata fornisce la soluzione richiesta. Per lo meno, è la risposta che stavo cercando!
spikyjt,

79

Le altre risposte non hanno funzionato per me. Ho continuato a cercare e ho trovato un post sul blog che descriveva come un team stava eseguendo non root all'interno di un container docker.

Ecco la versione 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 

Stavo usando FROM node:9.3per questo, ma sospetto che anche altre basi per container simili funzionerebbero.


Sto usando ubuntu:bionic-20180724.1. Ho usato questo approccio ma, dopo quanto sopra, non mi consente di installare un altro pacchetto. I allegate una linea a quanto sopra Dockerfileper installare un pacchetto con: RUN apt-get install -y tree. Tuttavia, mi ha dato questo messaggio di errore: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 Penso che devi cambiare quella riga per leggere RUN sudo apt-get install -y tree. Dopo aver impostato USERsu qualcosa di diverso da root, è necessario utilizzare sudoper tutti i comandi che richiedono rootprivilegi.
M. Scott Ford,

Ah grazie! Perso quello. Non pensavo sudofosse permesso in un Dockerfile.
edesz,

Perfetto, proprio quello di cui avevo bisogno.
Arin Ekandem,

25

Per chiunque abbia questo problema con un contenitore già in esecuzione e non desidera necessariamente ricostruirlo, il comando seguente si collega a un contenitore in esecuzione con privilegi di root:

docker exec -ti -u root container_name bash

Puoi anche connetterti utilizzando il suo ID, anziché il suo nome, trovandolo con:

docker ps -l

Per salvare le modifiche in modo che siano ancora presenti al successivo avvio del contenitore (o cluster comporre docker):

docker commit container_id image_name

Per avviare un contenitore che non è in esecuzione e connettersi come root:

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

Per copiare da un contenitore in esecuzione:

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

Per esportare una copia dell'immagine:

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

Che è possibile ripristinare su un'altra installazione Docker usando:

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

È molto più veloce ma richiede più spazio per non comprimere, usando:

docker save container | dir/file.tar

E:

cat dir/file.tar | docker load

17

se vuoi connetterti al container e installare qualcosa
usando apt-get
come prima risposta di nostro fratello "Tomáš Záluský"

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

quindi provare a

ESEGUI apt-get update o apt-get 'tutto quello che vuoi'

ha funzionato con me spero sia utile per tutti


5

Se SUDO o apt-get non sono accessibili all'interno del contenitore, è possibile utilizzare, sotto l'opzione, nel contenitore in esecuzione.

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" è il mio ID contenitore e qui è un esempio funzionante dal mio terminale:

inserisci qui la descrizione dell'immagine


3

Ecco come installo un utente non root con l'immagine di base di 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

Cosa succede con il codice sopra:

  • L'utente e il gruppo foosono stati creati.
  • L'utente fooviene aggiunto al gruppo fooe sudo.
  • L' uide gidviene impostato al valore del 999.
  • La home directory è impostata su /home/foo.
  • La shell è impostata su /bin/bash.
  • Il sedcomando esegue gli aggiornamenti in linea per il /etc/sudoersfile per consentire fooe rootagli utenti senza password l'accesso al sudogruppo.
  • Il sedcomando disabilita la #includedirdirettiva che consentirebbe a qualsiasi file nelle sottodirectory di sovrascrivere questi aggiornamenti in linea.

2

Se hai un contenitore in esecuzione come root che esegue uno script (che non puoi modificare) che necessita dell'accesso al sudocomando, puoi semplicemente creare un nuovo sudoscript nel tuo $PATHche chiama il comando passato.

ad es. nel 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

1
A seconda delle immagini docker che stai utilizzando (nel mio caso Ubuntu: 18.04), potresti dover rimuovere -eil file echo. Altrimenti sarà presente nel file stesso, rendendolo non funzionale.
stiller_leser,

Ottima idea, ma questo non funzionerà se il comando originale utilizza opzioni sudo, come sudo -E ls. Tenterà di eseguire -E ls.
Wisbucky,

2

Questo potrebbe non funzionare per tutte le immagini, ma alcune immagini contengono già un utente root, come nell'immagine jupyterhub / singleuser. Con quell'immagine è semplicemente:

USER root
RUN sudo apt-get update

1

Usa alias.

alias sudo=''

Semplice ma efficiente. Non dimenticare di aggiungerlo a ~ / .bash_aliases in modo che funzioni dopo aver aperto una nuova shell.

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

Poiché l'utente è root predefinito in Docker, 'ignorare' il comando sudo è il modo più semplice.


0

A differenza della risposta accettata , io uso usermodinvece.

Supponiamo che sia già stato effettuato l'accesso come root nella finestra mobile e "fruit" è il nuovo nome utente non root che voglio aggiungere, esegui semplicemente questi comandi:

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

Ricorda di salvare l'immagine dopo l'aggiornamento. Utilizzare docker psper ottenere <ID CONTENITORE> e <IMAGE> della finestra mobile attualmente in esecuzione, quindi eseguire docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>per salvare l'immagine della finestra mobile.

Quindi prova con:

su fruit
sudo whoami

Oppure prova con l'accesso diretto (assicurati di salvare prima l'immagine) come utente non root all'avvio della finestra mobile:

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

È possibile utilizzare sudo -kper reimpostare il timestamp della richiesta password:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.