Como usar o sudo dentro de um contêiner de docker?

259

Normalmente, os contêineres do docker são executados usando a raiz do usuário . Eu gostaria de usar um usuário diferente, o que não é problema ao usar a diretiva USER do docker. Mas esse usuário deve poder usar o sudo dentro do contêiner. Este comando está ausente.

Aqui está um Dockerfile simples para esse fim:

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

Ao executar este contêiner, eu entrei com o usuário 'docker'. Quando tento usar o sudo, o comando não é encontrado. Então, tentei instalar o pacote sudo dentro do meu Dockerfile usando

RUN apt-get install sudo

Isso resulta em Não foi possível localizar o pacote sudo

drubb
fonte
Apenas dê o grupo sudo ao usuário. askubuntu.com/questions/7477/…
Regan

Respostas:

242

Apenas entendi. Como regan apontou, eu tive que adicionar o usuário ao grupo sudoers. Mas o principal motivo foi que eu tinha esquecido de atualizar o cache dos repositórios, então o apt-get não conseguiu encontrar o pacote sudo. Está funcionando agora. Aqui está o 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
fonte
8
não funciona em centos. o addusercomando cuspe a ajuda de uso para useradd
Emad
Para o CentOS, você pode adicionar um usuário e um grupo, criar um arquivo de fragmento /etc/sudoers.d/e definir as permissões 440nesse arquivo. Em seguida, o usuário teria acesso ao sudo no CentOS, 6 ou superior. 5 você precisará adicionar a #includedir /etc/sudoers.ddiretiva em/etc/sudoers
FilBot3 3/16/16
Não funciona para mim. Eu tenho esses erros: E: Não foi possível abrir o arquivo de bloqueio / var / lib / apt / lists / lock - open (13: Permissão negada) E: Não foi possível bloquear o diretório / var / lib / apt / lists /
Marosinho
1
Isso não parece estar funcionando para a imagem do docker do Ubuntu 18.04
viggy 04/04
100

Quando nem sudo nem apt-get estão disponíveis no contêiner, você também pode pular para o contêiner em execução como usuário root usando o comando

docker exec -u root -t -i container_id /bin/bash
Tomáš Záluský
fonte
Essa é uma solução muito melhor para o que o OP provavelmente deseja alcançar, mesmo que a resposta aceita forneça a solução solicitada. No mínimo, é a resposta que eu estava procurando!
spikyjt
79

As outras respostas não funcionaram para mim. Continuei pesquisando e encontrei uma postagem no blog que abordava como uma equipe estava executando não-root dentro de um contêiner de docker.

Aqui está a versão 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 

Eu estava usando FROM node:9.3para isso, mas suspeito que outras bases de contêineres semelhantes funcionariam também.

Scott Ford
fonte
Eu estou usando ubuntu:bionic-20180724.1. Usei essa abordagem, mas, após o exposto, ela não me permite instalar outro pacote. Eu anexada uma linha para a acima Dockerfile, a fim de instalar um pacote com: RUN apt-get install -y tree. No entanto, ele me deu esta mensagem de erro: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 Eu acho que você precisa mudar essa linha para ler RUN sudo apt-get install -y tree. Depois de definir USERpara algo diferente de root, você precisará usar sudopara qualquer comando que exija rootprivilégios.
M. Scott Ford
Ah obrigada! Perdeu isso. Eu não acho que sudofoi permitido em um arquivo Docker.
Edesz 22/08/19
Perfeito, exatamente o que eu precisava.
Arin Ekandem
25

Para quem tem esse problema com um contêiner já em execução e não deseja necessariamente reconstruir, o comando a seguir se conecta a um contêiner em execução com privilégios de root:

docker exec -ti -u root container_name bash

Você também pode se conectar usando seu ID, em vez de seu nome, localizando-o com:

docker ps -l

Para salvar suas alterações para que elas ainda estejam lá quando você iniciar o próximo contêiner (ou cluster de docker-componha):

docker commit container_id image_name

Para iniciar um contêiner que não está em execução e conectar-se como root:

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

Para copiar de um contêiner em execução:

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

Para exportar uma cópia da imagem:

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

Que você pode restaurar para outra instalação do Docker usando:

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

É muito mais rápido, mas ocupa mais espaço para não compactar, usando:

docker save container | dir/file.tar

E:

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

se você deseja se conectar ao container e instalar algo
usando o apt-get
first, como resposta acima do nosso irmão "Tomáš Záluský"

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

então tente

Execute o apt-get update ou apt-get 'o que quiser'

funcionou comigo espero que seja útil para todos

Ismail
fonte
5

Se SUDO ou apt-get não estiver acessível dentro do contêiner, você pode usar a opção abaixo na execução de contêiner.

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" é o meu ID de contêiner e aqui está um exemplo de trabalho do meu terminal:

insira a descrição da imagem aqui

Yogi Ghorecha
fonte
3

Veja como eu configuro um usuário não root com a imagem 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

O que acontece com o código acima:

  • O usuário e o grupo foosão criados.
  • O usuário fooé adicionado ao grupo fooe sudo.
  • O uide gidé definido como o valor de 999.
  • O diretório inicial está definido como /home/foo.
  • O shell está definido como /bin/bash.
  • O sedcomando faz atualizações embutidas no /etc/sudoersarquivo para permitir fooe rootaos usuários acesso sem senha ao sudogrupo.
  • O sedcomando desativa a #includedirdiretiva que permitiria que qualquer arquivo nos subdiretórios substituísse essas atualizações embutidas.
Seth Bergman
fonte
2

Se você tiver um contêiner em execução como root que executa um script (que não pode ser alterado) que precisa de acesso ao sudocomando, basta criar um novo sudoscript $PATHque chame o comando passado.

Por exemplo, no seu 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
fonte
1
Dependendo das imagens do docker que você está usando (no meu caso Ubuntu: 18.04), pode ser necessário removê -e-lo do echo. Caso contrário, ele estará presente no próprio arquivo, tornando-o infuncional.
stiller_leser
Boa ideia, mas isso não funcionará se o comando original estiver usando opções sudo, como sudo -E ls. Ele tentará executar -E ls.
wisbucky
2

Isso pode não funcionar para todas as imagens, mas algumas imagens já contêm um usuário raiz, como na imagem jupyterhub / singleuser. Com essa imagem é simplesmente:

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

Use Alias.

alias sudo=''

Simples, mas eficiente. Não se esqueça de anexá-lo a ~ / .bash_aliases, para que ele funcione depois que você abrir um novo shell.

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

Como o usuário é a raiz padrão no Docker, 'ignorar' o comando sudo é a maneira mais fácil.

Dogkiller87
fonte
0

Ao contrário da resposta aceita , eu uso usermod.

Suponha que você já tenha efetuado login como root na janela de encaixe e "fruit" seja o novo nome de usuário não raiz que quero adicionar, basta executar estes comandos:

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

Lembre-se de salvar a imagem após a atualização. Use docker pspara obter o <CONTAINER ID> e <IMAGE> do docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>docker em execução, e execute para salvar a imagem do docker.

Depois teste com:

su fruit
sudo whoami

Ou teste por login direto (assegure-se de salvar a imagem primeiro) como esse usuário não raiz ao iniciar a janela de encaixe:

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

Você pode usar sudo -kpara redefinir o carimbo de data / hora do prompt de senha:

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