Comment utiliser sudo dans un conteneur Docker?

259

Normalement, les conteneurs Docker sont exécutés à l'aide de la racine utilisateur . Je voudrais utiliser un autre utilisateur, ce qui ne pose aucun problème en utilisant la directive USER de Docker. Mais cet utilisateur devrait pouvoir utiliser sudo à l'intérieur du conteneur. Cette commande est manquante.

Voici un Dockerfile simple à cet effet:

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

En exécutant ce conteneur, je me connecte avec l'utilisateur 'docker'. Lorsque j'essaie d'utiliser sudo, la commande est introuvable. J'ai donc essayé d'installer le paquet sudo dans mon Dockerfile en utilisant

RUN apt-get install sudo

Cela se traduit par impossible de localiser le package sudo

drubb
la source
Donnez simplement le groupe sudo à l'utilisateur. askubuntu.com/questions/7477/…
Regan

Réponses:

242

Viens de le recevoir. Comme l'a souligné regan, j'ai dû ajouter l'utilisateur au groupe sudoers. Mais la raison principale était que j'avais oublié de mettre à jour le cache des référentiels, donc apt-get n'a pas pu trouver le paquet sudo. Ça marche maintenant. Voici le code complété:

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
la source
8
ne fonctionne pas dans les centos. la addusercommande crache l'aide à l'utilisation pouruseradd
Emad
Pour CentOS, vous pouvez ajouter un utilisateur et un groupe, puis créer un fichier de partition sous /etc/sudoers.d/et définir les autorisations 440sur ce fichier. Ensuite, l'utilisateur aurait un accès sudo sous CentOS, 6 et plus. 5 vous devrez ajouter la #includedir /etc/sudoers.ddirective/etc/sudoers
FilBot3
Ça ne marche pas pour moi. J'ai ces erreurs: E: impossible d'ouvrir le fichier de verrouillage / var / lib / apt / lists / lock - open (13: autorisation refusée) E: impossible de verrouiller le répertoire / var / lib / apt / lists /
Marosinho
1
Cela ne semble pas fonctionner pour l'image docker d'Ubuntu 18.04
viggy
100

Lorsque ni sudo ni apt-get n'est disponible dans le conteneur, vous pouvez également accéder au conteneur en cours d'exécution en tant qu'utilisateur root à l'aide de la commande

docker exec -u root -t -i container_id /bin/bash
Tomáš Záluský
la source
C'est une bien meilleure solution à ce que le PO souhaite probablement réaliser, même si la réponse acceptée donne la solution demandée. À tout le moins, c'est la réponse que je cherchais!
spikyjt
80

Les autres réponses n'ont pas fonctionné pour moi. J'ai continué à chercher et j'ai trouvé un article de blog qui couvrait comment une équipe exécutait non root à l'intérieur d'un conteneur Docker.

Voici la version 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 

J'utilisais FROM node:9.3pour cela, mais je soupçonne que d'autres bases de conteneurs similaires fonctionneraient également.

M. Scott Ford
la source
J'utilise ubuntu:bionic-20180724.1. J'ai utilisé cette approche mais, après ce qui précède, elle ne me permet pas d'installer un autre package. Une ligne I annexé au - dessus Dockerfileafin d'installer un package avec: RUN apt-get install -y tree. Cependant, cela m'a donné ce message d'erreur: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 Je pense que vous devez changer cette ligne pour lire RUN sudo apt-get install -y tree. Après avoir défini le USERsur autre chose que root, vous devrez utiliser sudopour toutes les commandes qui nécessitent des rootprivilèges.
M. Scott Ford
Ah merci! Ça m'a manqué. Je ne pensais pas que sudoc'était autorisé dans un Dockerfile.
edesz
Parfait, juste ce dont j'avais besoin.
Arin Ekandem
25

Pour toute personne qui a ce problème avec un conteneur déjà en cours d'exécution et qui ne veut pas nécessairement reconstruire, la commande suivante se connecte à un conteneur en cours d'exécution avec des privilèges root:

docker exec -ti -u root container_name bash

Vous pouvez également vous connecter en utilisant son ID, plutôt que son nom, en le trouvant avec:

docker ps -l

Pour enregistrer vos modifications afin qu'elles soient toujours là au prochain lancement du conteneur (ou du cluster de composition de docker):

docker commit container_id image_name

Pour démarrer un conteneur qui n'est pas en cours d'exécution et se connecter en tant que root:

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

Pour copier à partir d'un conteneur en cours d'exécution:

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

Pour exporter une copie de l'image:

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

Que vous pouvez restaurer dans une autre installation Docker en utilisant:

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

C'est beaucoup plus rapide mais prend plus de place pour ne pas compresser, en utilisant:

docker save container | dir/file.tar

Et:

cat dir/file.tar | docker load
Chris
la source
17

si vous voulez vous connecter au conteneur et installer quelque chose en
utilisant apt-get en
premier comme réponse ci-dessus de notre frère "Tomáš Záluský"

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

puis essayez de

Exécutez la mise à jour apt-get ou apt-get «tout ce que vous voulez»

ça a fonctionné avec moi j'espère que c'est utile pour tous

Ismail
la source
5

Si SUDO ou apt-get n'est pas accessible à l'intérieur du conteneur, vous pouvez utiliser l'option ci-dessous pour exécuter le conteneur.

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" est mon ID de conteneur et voici un exemple de travail de mon terminal:

entrez la description de l'image ici

Yogi Ghorecha
la source
3

Voici comment configurer un utilisateur non root avec l'image de 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

Que se passe-t-il avec le code ci-dessus:

  • L'utilisateur et le groupe foosont créés.
  • L'utilisateur fooest ajouté à la fois au fooet au sudogroupe.
  • Le uidet gidest défini sur la valeur de 999.
  • Le répertoire personnel est défini sur /home/foo.
  • Le shell est défini sur /bin/bash.
  • La sedcommande effectue des mises à jour en ligne du /etc/sudoersfichier pour autoriser les utilisateurs fooet l' rootaccès sans mot de passe au sudogroupe.
  • La sedcommande désactive la #includedirdirective qui permettrait à tous les fichiers des sous-répertoires de remplacer ces mises à jour en ligne.
Seth Bergman
la source
2

Si vous avez un conteneur en cours d'exécution en tant que root qui exécute un script (que vous ne pouvez pas modifier) ​​qui a besoin d'accéder à la sudocommande, vous pouvez simplement créer un nouveau sudoscript dans votre $PATHqui appelle la commande passée.

Par exemple, dans votre 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
la source
1
Selon les images de docker que vous utilisez (dans mon cas Ubuntu: 18.04), vous devrez peut-être supprimer le -edu echo. Sinon, il sera présent dans le fichier lui-même, ce qui le rendra fonctionnel.
stiller_leser
Bonne idée, mais cela ne fonctionnera pas si la commande d'origine utilise des options sudo, telles que sudo -E ls. Il va essayer de s'exécuter -E ls.
wisbucky
2

Cela peut ne pas fonctionner pour toutes les images, mais certaines images contiennent déjà un utilisateur root, comme dans l'image jupyterhub / singleuser. Avec cette image, c'est tout simplement:

USER root
RUN sudo apt-get update
Alex Kaszynski
la source
1

Utilisez l'alias.

alias sudo=''

Simple mais efficace. N'oubliez pas de l'ajouter à ~ / .bash_aliases pour qu'il fonctionne après avoir ouvert un nouveau shell.

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

Étant donné que l'utilisateur est root par défaut dans Docker, «ignorer» la commande sudo est le moyen le plus simple.

Dogkiller87
la source
0

Contrairement à la réponse acceptée , j'utilise à la usermodplace.

Supposons que vous êtes déjà connecté en tant que root dans Docker et que "fruit" est le nouveau nom d'utilisateur non root que je veux ajouter, exécutez simplement ces commandes:

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

N'oubliez pas d'enregistrer l'image après la mise à jour. Utilisez docker pspour obtenir <CONTAINER ID> et <IMAGE> du docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>docker en cours d' exécution, puis exécutez pour enregistrer l'image du docker.

Testez ensuite avec:

su fruit
sudo whoami

Ou testez par connexion directe (assurez-vous d'abord de sauvegarder l'image) en tant qu'utilisateur non root lors du lancement du docker:

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

Vous pouvez utiliser sudo -kpour réinitialiser l'horodatage de l'invite de mot de passe:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password
Fruit
la source