web-dev-qa-db-fra.com

Exécution de l'application dans Docker en tant qu'utilisateur non root

Après nouvelles de Shocker d'hier , il semble que les applications d'un conteneur Docker ne doivent pas être exécutées en tant que root. J'ai essayé de mettre à jour mon Dockerfile pour créer un utilisateur d'application, mais la modification des autorisations sur les fichiers d'application (tout en restant root) ne semble pas fonctionner. J'imagine que c'est parce que certaines autorisations LXC ne sont peut-être pas accordées à l'utilisateur root.

Voici mon Dockerfile:

# Node.js app Docker file

FROM dockerfile/nodejs
MAINTAINER Thom Nichols "[email protected]"

RUN useradd -ms /bin/bash node

ADD . /data
# This next line doesn't seem to have any effect:
RUN chown -R node /data 

ENV HOME /home/node
USER node

RUN cd /data && npm install

EXPOSE 8888

WORKDIR /data

CMD ["npm", "start"]

Assez simple, mais quand je ls -l tout est toujours la propriété de root:

[ node@ed7ae33e76e1:/data {docker-nonroot-user} ]$ ls -l /data
total 64K
-rw-r--r--  1 root root  383 Jun 18 20:32 Dockerfile
-rw-r--r--  1 root root  862 Jun 18 16:23 Gruntfile.js
-rw-r--r--  1 root root 1.2K Jun 18 15:48 README.md
drwxr-xr-x  4 root root 4.0K May 30 14:24 assets/
-rw-r--r--  1 root root  416 Jun  3 14:22 bower.json
-rw-r--r--  1 root root  930 May 30 01:50 config.js
drwxr-xr-x  4 root root 4.0K Jun 18 16:08 lib/
drwxr-xr-x 42 root root 4.0K Jun 18 16:04 node_modules/
-rw-r--r--  1 root root 2.0K Jun 18 16:04 package.json
-rw-r--r--  1 root root  118 May 30 18:35 server.js
drwxr-xr-x  3 root root 4.0K May 30 02:17 static/
drwxr-xr-x  3 root root 4.0K Jun 18 20:13 test/
drwxr-xr-x  3 root root 4.0K Jun  3 17:38 views/

Mon fichier docker mis à jour fonctionne très bien grâce à la clarification de @ creak sur le fonctionnement des volumes. Une fois que les fichiers initiaux sont chowned, npm install est exécuté en tant qu'utilisateur non root. Et grâce à un hook postinstall, npm exécute bower install && grunt assets qui prend en charge les étapes d’installation restantes et évite le besoin de npm install -g tous les outils de nœud tels que bower, grunt ou coffeescript.

74
thom_nic

Celui-ci est un peu délicat, il est en fait dû à l'image à partir de laquelle vous partez.

Si vous regardez la source , vous remarquerez que /data/ est un volume. Ainsi, tout ce que vous ferez dans Dockerfile sera ignoré et remplacé au moment de l’exécution par le volume monté à ce moment-là.

Vous pouvez chown à l'exécution en modifiant votre CMD en quelque chose comme CMD chown -R node /data && npm start.

14
creack

Consultez ce message: http://www.yegor256.com/2014/08/29/docker-non-root.html In rultor.com nous exécutons toutes les versions leurs propres conteneurs Docker. Et chaque fois avant d'exécuter les scripts à l'intérieur du conteneur, nous basculons vers un utilisateur non root. C'est ainsi:

adduser --disabled-password --gecos '' r
adduser r Sudo
echo '%Sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
su -m r -c /home/r/script.sh

r est l'utilisateur que nous utilisons.

26
yegor256

Mise à jour 2015-09-28

J'ai remarqué que ce message suscitait un peu d'attention. Un mot de conseil pour quiconque est potentiellement intéressé à faire quelque chose comme ça. J'essayais d'utiliser Python ou une autre langue comme enveloppe pour vos exécutions de script. Lors de l'exécution de scripts bash natifs, je rencontrais des problèmes lorsque j'essayais de transmettre divers arguments à mes conteneurs. Plus précisément, il y avait des problèmes avec l'interprétation/échappement de "et" caractères par le shell.


J'avais besoin de changer d'utilisateur pour une raison légèrement différente.

J'ai créé un image de menu fixe contenant une installation complète de ImageMagick et Ffmpeg avec le désir de pouvoir effectuer des transformations sur les images/vidéos de mon hôte. OS. Mon problème était qu’il s’agissait d’outils de ligne de commande. Il est donc légèrement plus délicat de les exécuter via docker, puis d’obtenir les résultats dans l’OS hôte. J'ai réussi à permettre cela en montant un volume de menu fixe. Cela semblait fonctionner correctement, sauf que la sortie image/vidéo sortait comme étant la propriété de root ​​(c'est-à-dire l'utilisateur sous lequel le conteneur docker était exécuté) plutôt que l'utilisateur qui a exécuté la commande.

J'ai regardé l'approche que @ François Zaninotto a mentionnée dans son réponse (vous pouvez voir l'intégralité du script de création ici ). C’était vraiment cool, mais j’ai préféré l’option de créer un script bash Shell que je voudrais ensuite enregistrer sur mon chemin. J'ai repris certains concepts de l'approche Makefile (en particulier la création d'utilisateurs/de groupes), puis j'ai créé le script Shell.

Voici un exemple de mon --- dockermagick script shell:

#!/bin/bash

### VARIABLES

DOCKER_IMAGE='acleancoder/imagemagick-full:latest'
CONTAINER_USERNAME='dummy'
CONTAINER_GROUPNAME='dummy'
HOMEDIR='/home/'$CONTAINER_USERNAME
GROUP_ID=$(id -g)
USER_ID=$(id -u)

### FUNCTIONS

create_user_cmd()
{
  echo \
    groupadd -f -g $GROUP_ID $CONTAINER_GROUPNAME '&&' \
    useradd -u $USER_ID -g $CONTAINER_GROUPNAME $CONTAINER_USERNAME '&&' \
    mkdir --parent $HOMEDIR '&&' \
    chown -R $CONTAINER_USERNAME:$CONTAINER_GROUPNAME $HOMEDIR
}

execute_as_cmd()
{
  echo \
    Sudo -u $CONTAINER_USERNAME HOME=$HOMEDIR
}

full_container_cmd()
{
  echo "'$(create_user_cmd) && $(execute_as_cmd) $@'"
}

### MAIN

eval docker run \
    --rm=true \
    -a stdout \
    -v $(pwd):$HOMEDIR \
    -w $HOMEDIR \
    $DOCKER_IMAGE \
    /bin/bash -ci $(full_container_cmd $@)

Ce script est lié à l'image 'acleancoder/imagemagick-full', mais vous pouvez le modifier en modifiant la variable en haut du script.

Ce qu'il fait fondamentalement est:

  • Créez un ID utilisateur et un groupe dans conteneur pour faire correspondre l'utilisateur qui exécute le script à partir de Host OS.
  • Monte le répertoire de travail actuel du OS hôte (à l'aide de volumes de menu fixe) dans répertoire de base pour l'utilisateur créé dans l'exécution conteneur de menu fixe.
  • Définit le répertoire tmp comme répertoire de travail pour le conteneur.
  • Transmet tous les arguments transmis au script, qui seront ensuite exécutés par le '/ bin/bash' de l'exécution conteneur docker.

Je peux maintenant exécuter les commandes ImageMagick/Ffmpeg sur les fichiers de mon système d'exploitation hôte. Par exemple, disons que je veux convertir une image MyImage.jpeg en un fichier PNG , je pourrais maintenant procéder comme suit:

$ cd ~/MyImages
$ ls
  MyImage.jpeg
$ dockermagick convert MyImage.jpeg Foo.png
$ ls
  Foo.png MyImage.jpeg

J'ai également attaché à la 'stdout' afin que je puisse exécuter la commande ImageMagick identifier pour obtenir des informations sur une image sur mon hôte, par exemple:

$ dockermagick identify MyImage.jpeg
  MyImage.jpeg JPEG 640x426 640x426+0+0 8-bit DirectClass 78.6KB 0.000u 0:00.000

Il y a des dangers évidents à monter dans le répertoire courant et à permettre la transmission de toute définition de commande arbitraire pour exécution. Mais il y a aussi beaucoup de façons de rendre le script plus sûr. J'exécute ceci dans mon propre environnement personnel non productif, donc ce n'est pas une préoccupation majeure pour moi. Mais je vous recommande vivement de prendre en compte les dangers si vous choisissez de développer ce script. Cela vaut également la peine de mentionner que ce script ne prend pas en compte un hôte OS X. Le make file à qui je dérobe des idées/concepts en tient compte, vous pouvez donc étendre ce script pour le faire.

Une autre limitation à noter est que je ne peux me référer qu'aux fichiers se trouvant actuellement dans le chemin pour lequel j'exécute le script. En raison de la façon dont je monte les volumes, les éléments suivants ne fonctionneraient pas:

$ cd ~/MyImages
$ ls
  MyImage.jpeg
$ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png
$ ls
  MyImage.jpeg

Il vaut mieux simplement aller dans le répertoire contenant l'image et l'exécuter directement. Bien sûr, je suis sûr qu'il existe des moyens de contourner cette limitation également, mais pour moi et mes besoins actuels, cela ira.

18
ctrlplusb

Note: Je réponds ici car, étant donné le titre générique, cette question apparaît dans Google lorsque vous recherchez une solution pour "Exécuter l'application dans Docker en tant qu'utilisateur non root. utilisateur". J'espère que cela aidera ceux qui sont coincés ici.

Avec Alpine Linux, vous pouvez créer un utilisateur système comme ceci:

RUN adduser -D -H -S -s /bin/false -u 1000 myuser

Tout ce qui se trouve dans Dockerfile après que cette ligne a été exécutée avec myuser.

myuser utilisateur a:

  • aucun mot de passe attribué
  • no home dir
  • pas de login shell
  • aucun accès root .

C'est de la part de adduser --help:

-h DIR      Home directory
-g GECOS    GECOS field
-s Shell    Login Shell
-G GRP      Add user to existing group
-S          Create a system user
-D          Don't assign a password
-H          Don't create home directory
-u UID      User id
-k SKEL     Skeleton directory (/etc/skel)
3
Rotareti

Remarque : Cette réponse est donnée car beaucoup de personnes recherchant une utilisation non root se retrouveront ici. Attention, cela ne résout pas le problème qui a provoqué le problème, mais aborde le titre et clarifie une réponse donnée par @ yegor256, qui utilise un utilisateur non root dans le conteneur. Cette réponse explique comment faire cela pour un cas d'utilisation non-debian/non-ubuntu. Cela ne résout pas le problème des volumes.

Sur les systèmes Red Hat, tels que Fedora et CentOS, cela peut être effectué de la manière suivante:

RUN adduser user && \
    echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \
    chmod 0440 /etc/sudoers.d/user

Dans votre fichier Docker, vous pouvez exécuter des commandes avec cet utilisateur en procédant comme suit:

RUN su - user -c "echo Hello $HOME"

Et la commande peut être exécutée en tant que:

CMD ["su","-","user","-c","/bin/bash"]

Un exemple de ceci peut être trouvé ici: https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16

0
gbraad