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


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

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

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.


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

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


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


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.

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

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

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.