Nach den gestrigen Nachrichten von Shocker scheint es, dass Apps in einem Docker-Container nicht als Root ausgeführt werden sollten. Ich habe versucht, meine zu aktualisieren Dockerfile
, um einen App-Benutzer zu erstellen, aber das Ändern der Berechtigungen für App-Dateien (solange sie noch root sind) scheint nicht zu funktionieren. Ich vermute, das liegt daran, dass dem Root-Benutzer möglicherweise keine LXC-Berechtigung erteilt wird.
Hier ist meine Docker-Datei:
# 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"]
Ziemlich einfach, aber wenn ich ls -l
alles noch im Besitz von root bin :
[ 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/
Meine aktualisierte Docker-Datei funktioniert hervorragend , da @ creak klargestellt hat, wie Volumes funktionieren. Sobald die anfänglichen Dateien chown
bearbeitet wurden, npm install
wird sie als Nicht-Root-Benutzer ausgeführt. Und dank eines postinstall
Hooks wird npm ausgeführt, bower install && grunt assets
das sich um die verbleibenden Installationsschritte kümmert und die Notwendigkeit von npm install -g
Node-Cli-Tools wie Bower, Grunzen oder Coffeescript vermeidet.
node
Benutzer erstellt wird?docker run -it myimage /bin/bash
und renne,whoami
bin ich angemeldet,node
was ich erwarten würde.Antworten:
Dieser ist etwas knifflig, er liegt tatsächlich an dem Bild, von dem Sie ausgehen.
Wenn Sie sich die Quelle ansehen , stellen Sie fest, dass
/data/
es sich um ein Volume handelt. Alles, was Sie in tun,Dockerfile
wird zur Laufzeit von dem Volume, das dann gemountet wird, verworfen und überschrieben.Sie können zur Laufzeit chown, indem Sie Ihre CMD auf so etwas wie ändern
CMD chown -R node /data && npm start
.quelle
CMD chown...
funktioniert das nicht, da dies ausgeführt wird, wenn dernode
Benutzer, der obv hat, keine Berechtigung zum Ändern der Berechtigungen von Dateien besitzt, deren Eigentümer er istroot
. Ich frage mich, ob es in Ordnung ist, wenn der Quellcode zur Laufzeit nicht beschreibbar ist, solange die App Zugriff auf einen beschreibbaren Speicherort für Protokolle und zur Laufzeit kompilierte Dateien hat. Ist es möglich, zur Laufzeit ein Volume zu erstellen, das nicht Root gehört?su node -c "npm start"
. Abhängig von Ihren Anforderungen sollte es jedoch in Ordnung sein, schreibgeschützt zu arbeiten, solange Sie Zugriff auf ein beschreibbares Verzeichnis haben./data
ein Band ist. Wenn ich dieses Verzeichnis in etwas anderes ändere/opt/foobar
oder/home/node/app
,chown
funktioniert es als Teil des Builds einwandfrei. Außerdem habe ich bestätigt, dasschown
-ing ein Volume in einem laufenden Container ebenfalls zu funktionieren scheint. Ich denke, die einfachste Lösung besteht darin, kein Volume für die App-Quellen zu verwenden. Ich habe meine resultierende Docker-Datei hier aktualisiert: gist.github.com/thom-nic/5e561e800cbc0f71555cÜberprüfen Sie diesen Beitrag: http://www.yegor256.com/2014/08/29/docker-non-root.html In rultor.com führen wir alle Builds in ihren eigenen Docker-Containern aus. Und jedes Mal, bevor wir die Skripte im Container ausführen, wechseln wir zu einem Benutzer ohne Rootberechtigung. Das ist wie:
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
ist der Benutzer, den wir verwenden.quelle
adduser -m --disabled-password --gecos '' r
Update 28.09.2015
Ich habe bemerkt, dass dieser Beitrag ein bisschen Aufmerksamkeit erhält. Ein Ratschlag für alle, die möglicherweise daran interessiert sind, so etwas zu tun. Ich würde versuchen, Python oder eine andere Sprache als Wrapper für Ihre Skriptausführungen zu verwenden. Beim Ausführen nativer Bash-Skripte hatte ich Probleme, als ich versuchte, verschiedene Argumente an meine Container weiterzuleiten. Insbesondere gab es Probleme mit der Interpretation / Flucht von "und" Zeichen durch die Shell.
Ich musste den Benutzer aus einem etwas anderen Grund wechseln.
Ich habe ein Docker-Image erstellt, das eine voll funktionsfähige Installation von ImageMagick und Ffmpeg enthält, mit dem Wunsch, dass ich Transformationen für Bilder / Videos in meinem Host-Betriebssystem durchführen kann. Mein Problem war, dass dies Befehlszeilentools sind, daher ist es etwas schwieriger, sie über Docker auszuführen und die Ergebnisse dann wieder in das Host-Betriebssystem zu übertragen. Ich habe es geschafft, dies durch das Mounten eines Docker-Volumes zu ermöglichen. Dies schien in Ordnung zu sein, außer dass die Bild- / Videoausgabe im Besitz von root war (dh dem Benutzer, unter dem der Docker-Container ausgeführt wurde) und nicht dem Benutzer, der den Befehl ausgeführt hat.
Ich habe mir den Ansatz angesehen, den @ François Zaninotto in seiner Antwort erwähnt hat (das vollständige Make-Skript finden Sie hier ). Es war wirklich cool, aber ich bevorzugte die Option, ein Bash-Shell-Skript zu erstellen, das ich dann auf meinem Pfad registrieren würde. Ich habe einige der Konzepte aus dem Makefile-Ansatz übernommen (insbesondere die Benutzer- / Gruppenerstellung) und dann das Shell-Skript erstellt.
Hier ist ein Beispiel für mein Dockermagick- Shell-Skript:
#!/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 $@)
Dieses Skript ist an das Bild 'acleancoder / imagemagick-full' gebunden. Dies kann jedoch durch Bearbeiten der Variablen oben im Skript geändert werden.
Was es im Grunde tut, ist:
Jetzt kann ich die ImageMagick / Ffmpeg- Befehle für Dateien auf meinem Host-Betriebssystem ausführen. Angenommen , ich möchte ein Bild MyImage.jpeg in eine PNG- Datei konvertieren , könnte ich jetzt Folgendes tun:
$ cd ~/MyImages $ ls MyImage.jpeg $ dockermagick convert MyImage.jpeg Foo.png $ ls Foo.png MyImage.jpeg
Ich habe auch an das 'stdout' angehängt, damit ich den ImageMagick-Identifizierungsbefehl ausführen kann, um Informationen zu einem Bild auf meinem Host abzurufen, z.
Es besteht die offensichtliche Gefahr, das aktuelle Verzeichnis bereitzustellen und die Weitergabe beliebiger Befehlsdefinitionen zur Ausführung zuzulassen. Es gibt aber auch viele Möglichkeiten, das Skript sicherer zu machen. Ich führe dies in meiner eigenen nicht produktiven persönlichen Umgebung aus, daher sind diese für mich nicht von größter Bedeutung. Ich würde Ihnen jedoch wärmstens empfehlen, die Gefahren zu berücksichtigen, wenn Sie dieses Skript erweitern. Erwähnenswert ist auch, dass dieses Skript keinen OS X-Host berücksichtigt. Die make-Datei , aus der ich Ideen / Konzepte stehle, berücksichtigt dies, sodass Sie dieses Skript dazu erweitern können.
Eine weitere Einschränkung ist, dass ich nur auf Dateien verweisen kann, die sich derzeit in dem Pfad befinden, für den ich das Skript ausführe. Dies liegt an der Art und Weise, wie ich die Volumes einbinde, sodass Folgendes nicht funktionieren würde:
$ cd ~/MyImages $ ls MyImage.jpeg $ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png $ ls MyImage.jpeg
Gehen Sie am besten in das Verzeichnis, in dem sich das Bild befindet, und führen Sie es direkt aus. Natürlich bin ich mir sicher, dass es auch Möglichkeiten gibt, diese Einschränkung zu umgehen, aber für mich und meine aktuellen Bedürfnisse wird dies ausreichen.
quelle
docker
Wrapper integriert.echo "su $CONTAINER_USERNAME -c "
in der Funktion execute_as_cmd ().Hinweis : Ich antworte hier, da diese Frage angesichts des generischen Titels in Google angezeigt wird, wenn Sie nach einer Lösung für "Ausführen einer App in Docker als Nicht-Root-Benutzer" suchen. Hoffe es hilft denen, die hier gestrandet sind.
Mit Alpine Linux können Sie einen Systembenutzer wie folgt erstellen:
RUN adduser -D -H -S -s /bin/false -u 1000 myuser
Alles in der
Dockerfile
nach dieser Zeile wird mit ausgeführtmyuser
.myuser
Benutzer hat:Dies ist aus
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)
quelle
Hinweis : Diese Antwort wird gegeben, weil viele Leute, die nach einer Verwendung ohne Rootberechtigung suchen, hier landen werden. Beachten Sie, dass hier nicht das Problem behoben wird, das das Problem verursacht hat, sondern der Titel und die Erläuterung einer Antwort von @ yegor256, bei der ein Benutzer ohne Rootberechtigung im Container verwendet wird. Diese Antwort erklärt, wie dies für den Anwendungsfall Nicht-Debian / Nicht-Ubuntu erreicht werden kann. Damit wird das Problem mit Volumes nicht behoben.
Auf Red Hat-basierten Systemen wie Fedora und CentOS kann dies folgendermaßen erfolgen:
RUN adduser user && \ echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \ chmod 0440 /etc/sudoers.d/user
In Ihrer Docker-Datei können Sie als dieser Benutzer Befehle ausführen, indem Sie Folgendes tun:
RUN su - user -c "echo Hello $HOME"
Der Befehl kann wie folgt ausgeführt werden:
CMD ["su","-","user","-c","/bin/bash"]
Ein Beispiel hierfür finden Sie hier: https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16
quelle
>>
. Wenn Sie einem Benutzer vollen Sudo-Zugriff auf root gewähren, werden alle Vorteile der Ausführung des Containers als Nicht-Root-Benutzer zunichte gemacht.