node.js docker lxc

node.js - Ejecución de la aplicación dentro de Docker como usuario no root



lxc (5)

Actualización 2015-09-28

Me he dado cuenta de que esta publicación ha recibido un poco de atención. Un consejo para cualquier persona que esté potencialmente interesada en hacer algo como esto. Intentaría usar Python u otro lenguaje como envoltorio para las ejecuciones de tus scripts. Haciendo scripts nativos de bash tuve problemas al tratar de pasar una variedad de argumentos a mis contenedores. Específicamente, hubo problemas con la interpretación / escape de los caracteres "y" por el caparazón.

Necesitaba cambiar al usuario por una razón ligeramente diferente.

Creé una imagen acoplable que albergaba una instalación completa de ImageMagick y Ffmpeg con el deseo de poder hacer transformaciones en imágenes / videos dentro de mi sistema operativo host. Mi problema es que estas son herramientas de línea de comandos, por lo que es un poco más complicado ejecutarlas a través de la ventana acoplable y luego volver a obtener los resultados en el sistema operativo host. Me las arreglé para permitir esto al montar un volumen docker. Esto pareció funcionar bien, excepto que la salida de imagen / video estaba siendo propiedad de root (es decir, el usuario en el que se estaba ejecutando el contenedor acoplable), en lugar del usuario que ejecutó el comando.

Miré el enfoque que @ François Zaninotto menciona en su answer (aquí puedes ver el guión completo). Fue genial, pero preferí la opción de crear un script de bash shell que luego registraría en mi ruta. Tomé algunos de los conceptos del enfoque Makefile (específicamente la creación del usuario / grupo) y luego creé el script de shell.

Aquí hay un ejemplo de mi script de shell dockermagick :

#!/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 $@)

Este script está vinculado a la imagen ''acleancoder / imagemagick-full'', pero eso se puede modificar editando la variable en la parte superior del script.

Lo que básicamente hace es:

  • Cree una identificación de usuario y un grupo dentro del contenedor para que coincida con el usuario que ejecuta la secuencia de comandos desde el sistema operativo host .
  • Monta el directorio de trabajo actual del sistema operativo host (utilizando los volúmenes del acoplador) en el directorio de inicio para el usuario que creamos dentro del contenedor del acoplador de ejecución.
  • Establece el directorio tmp como el directorio de trabajo para el contenedor .
  • Pasa cualquier argumento que se pase al script, que luego será ejecutado por el '' / bin / bash '' del contenedor acoplable en ejecución.

Ahora puedo ejecutar los comandos de ImageMagick / Ffmpeg contra archivos en mi sistema operativo host. Por ejemplo, supongamos que quiero convertir una imagen MyImage.jpeg en un archivo PNG , ahora podría hacer lo siguiente:

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

También me he adjuntado a ''stdout'' para poder ejecutar el comando de identificación de ImageMagick para obtener información sobre una imagen en mi host, por ejemplo:

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

Existen peligros obvios al montar el directorio actual y permitir que cualquier definición de comando arbitraria se transfiera para su ejecución. Pero también hay muchas maneras de hacer que el script sea más seguro. Estoy ejecutando esto en mi propio entorno personal no productivo, por lo que estos no son de gran preocupación para mí. Pero le recomiendo que tome los peligros en consideración si decide ampliar este guión. También merece la pena mencionar que este script no tiene en cuenta un host OS X. El here que robo ideas / conceptos sí lo tiene en cuenta, por lo que podría extender este script para hacerlo.

Otra limitación a tener en cuenta es que solo puedo referirme a archivos actualmente en la ruta para la cual estoy ejecutando el script. Esto se debe a la forma en que estoy montando los volúmenes, por lo que lo siguiente no funcionaría:

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

Lo mejor es ir al directorio que contiene la imagen y ejecutarla directamente. Por supuesto, estoy seguro de que hay formas de evitar esta limitación también, pero para mí y mis necesidades actuales, esto servirá.

Después de las noticias de ayer de Shocker , parece que las aplicaciones dentro de un contenedor Docker no deberían ejecutarse como root. Traté de actualizar mi Dockerfile para crear un usuario de la aplicación, sin embargo, cambiar los permisos en los archivos de la aplicación (aunque todavía es root) no parece funcionar. Supongo que esto se debe a que algunos permisos de LXC no se otorgan al usuario raíz, ¿no es así?

Aquí está mi archivo Docker:

# 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"]

Bastante sencillo, pero cuando ls -l todo sigue siendo propiedad 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/

Mi archivo docker actualizado funciona muy bien gracias a la aclaración de @crunch de cómo funcionan los volúmenes. Una vez que los archivos iniciales se seleccionan, la npm install se ejecuta como usuario no root. Y gracias a un gancho postinstall , npm ejecuta bower bower install && grunt assets que se encarga de los pasos de instalación restantes y evita la necesidad de npm install -g herramientas de cli de nodo como bower, grunt o coffeescript.


Este es un poco complicado, en realidad se debe a la imagen desde la que comienzas.

Si miras la fuente , notas que /data/ es un volumen. Entonces, todo lo que haga en Dockerfile será descartado y anulado en tiempo de ejecución por el volumen que se Dockerfile en ese momento.

Puede CMD chown -R node /data && npm start en tiempo de ejecución cambiando su CMD a algo como CMD chown -R node /data && npm start .


Verifique esta publicación: http://www.yegor256.com/2014/08/29/docker-non-root.html En rultor.com ejecutamos todas las construcciones en sus propios contenedores Docker. Y cada vez antes de ejecutar las secuencias de comandos dentro del contenedor, cambiamos a un usuario no root. Así es como:

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 es el usuario que estamos usando.


Nota : Esta respuesta se da porque muchas personas que buscan un uso no root terminarán aquí. Tenga en cuenta que esto no aborda el problema que causó el problema, sino que trata el título y la aclaración de una respuesta dada por @ yegor256, que utiliza un usuario no root dentro del contenedor. Esta respuesta explica cómo lograr esto para el caso de uso no-debian / no-ubuntu. Esto no está abordando el problema con los volúmenes.

En sistemas basados ​​en Red Hat, como Fedora y CentOS, esto se puede hacer de la siguiente manera:

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

En tu archivo Docker puedes ejecutar comandos como este usuario haciendo:

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

Y el comando se puede ejecutar como:

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

Un ejemplo de esto se puede encontrar aquí: https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16


Nota : respondo aquí porque, dado el título genérico, esta pregunta aparece en google cuando busca una solución para "Ejecutar aplicación dentro de Docker como usuario no root". Espero que ayude a los que están varados aquí.

Con Alpine Linux puede crear un usuario del sistema como este:

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

Todo en el Dockerfile después de esta línea se ejecuta con myuser .

myuser usuario usuario tiene:

  • sin contraseña asignada
  • no dir de inicio
  • sin shell de inicio de sesión
  • sin acceso a la raíz .

Esto es 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)