Switching users inside Docker image to a non-root user

169,230

Solution 1

You should not use su in a dockerfile, however you should use the USER instruction in the Dockerfile.

At each stage of the Dockerfile build, a new container is created so any change you make to the user will not persist on the next build stage.

For example:

RUN whoami
RUN su test
RUN whoami

This would never say the user would be test as a new container is spawned on the 2nd whoami. The output would be root on both (unless of course you run USER beforehand).

If however you do:

RUN whoami
USER test
RUN whoami

You should see root then test.

Alternatively you can run a command as a different user with sudo with something like

sudo -u test whoami

But it seems better to use the official supported instruction.

Solution 2

As a different approach to the other answer, instead of indicating the user upon image creation on the Dockerfile, you can do so via command-line on a particular container as a per-command basis.

With docker exec, use --user to specify which user account the interactive terminal will use (the container should be running and the user has to exist in the containerized system):

docker exec -it --user [username] [container] bash

See https://docs.docker.com/engine/reference/commandline/exec/

Solution 3

In case you need to perform privileged tasks like changing permissions of folders you can perform those tasks as a root user and then create a non-privileged user and switch to it.

FROM <some-base-image:tag>

# Switch to root user
USER root # <--- Usually you won't be needed it - Depends on base image

# Run privileged command
RUN apt install <packages>
RUN apt <privileged command>

# Set user and group
ARG user=appuser
ARG group=appuser
ARG uid=1000
ARG gid=1000
RUN groupadd -g ${gid} ${group}
RUN useradd -u ${uid} -g ${group} -s /bin/sh -m ${user} # <--- the '-m' create a user home directory

# Switch to user
USER ${uid}:${gid}

# Run non-privileged command
RUN apt <non-privileged command>

Solution 4

Add this line to docker file

USER <your_user_name>

Use docker instruction USER

Solution 5

You should also be able to do:

apt install sudo

sudo -i -u tomcat

Then you should be the tomcat user. It's not clear which Linux distribution you're using, but this works with Ubuntu 18.04 LTS, for example.

Share:
169,230

Related videos on Youtube

Jan Vladimir Mostert
Author by

Jan Vladimir Mostert

Updated on June 24, 2021

Comments

  • Jan Vladimir Mostert
    Jan Vladimir Mostert almost 3 years

    I'm trying to switch user to the tomcat7 user in order to setup SSH certificates.

    When I do su tomcat7, nothing happens.

    whoami still ruturns root after doing su tomcat7

    Doing a more /etc/passwd, I get the following result which clearly shows that a tomcat7 user exists:

    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/bin/sh
    bin:x:2:2:bin:/bin:/bin/sh
    sys:x:3:3:sys:/dev:/bin/sh
    sync:x:4:65534:sync:/bin:/bin/sync
    games:x:5:60:games:/usr/games:/bin/sh
    man:x:6:12:man:/var/cache/man:/bin/sh
    lp:x:7:7:lp:/var/spool/lpd:/bin/sh
    mail:x:8:8:mail:/var/mail:/bin/sh
    news:x:9:9:news:/var/spool/news:/bin/sh
    uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
    proxy:x:13:13:proxy:/bin:/bin/sh
    www-data:x:33:33:www-data:/var/www:/bin/sh
    backup:x:34:34:backup:/var/backups:/bin/sh
    list:x:38:38:Mailing List Manager:/var/list:/bin/sh
    irc:x:39:39:ircd:/var/run/ircd:/bin/sh
    gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
    nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
    libuuid:x:100:101::/var/lib/libuuid:/bin/sh
    messagebus:x:101:104::/var/run/dbus:/bin/false
    colord:x:102:105:colord colour management daemon,,,:/var/lib/colord:/bin/false
    saned:x:103:106::/home/saned:/bin/false
    tomcat7:x:104:107::/usr/share/tomcat7:/bin/false
    

    What I'm trying to work around is this error in Hudson:

    Command "git fetch -t git@________.co.za:_______/_____________.git +refs/heads/*:refs/remotes/origin/*" returned status code 128: Host key verification failed.
    

    This is my Dockerfile, it takes an existing hudson war file and config that is tarred and builds an image, hudson runs fine, it just can't access git due to certificates not existing for user tomcat7.

    FROM debian:wheezy
    
    # install java on image
    RUN apt-get update
    RUN apt-get install -y openjdk-7-jdk tomcat7
    
    # install hudson on image
    RUN rm -rf /var/lib/tomcat7/webapps/*
    ADD ./ROOT.tar.gz /var/lib/tomcat7/webapps/
    
    # copy hudson config over to image
    RUN mkdir /usr/share/tomcat7/.hudson
    ADD ./dothudson.tar.gz /usr/share/tomcat7/
    RUN chown -R tomcat7:tomcat7 /usr/share/tomcat7/
    
    # add ssh certificates
    RUN mkdir /root/.ssh
    ADD ssh.tar.gz /root/
    
    # install some dependencies
    RUN apt-get update
    RUN apt-get install --y maven
    RUN apt-get install --y git
    RUN apt-get install --y subversion
    
    # background script
    ADD run.sh /root/run.sh
    RUN chmod +x /root/run.sh
    
    # expose port 8080
    EXPOSE 8080
    
    
    CMD ["/root/run.sh"]
    

    I'm using the latest version of Docker (Docker version 1.0.0, build 63fe64c/1.0.0), is this a bug in Docker or am I missing something in my Dockerfile?

    • icecrime
      icecrime almost 10 years
      Are you aware of the USER Dockerfile instruction?
    • Jan Vladimir Mostert
      Jan Vladimir Mostert almost 10 years
      Nope, what do you suggest I use it for?
    • Jan Vladimir Mostert
      Jan Vladimir Mostert almost 10 years
      Would it be possible to generate certificates via the Dockerfile using the USER instruction?
    • icecrime
      icecrime almost 10 years
      Everything you RUN after a USER instruction is done under the corresponding uid, so although I'm not sure I perfectly understand your problem, it looks it might be what you're looking for.
    • davidA
      davidA about 8 years
      @icecrime not everything, unfortunately. COPY creates files as uid 0, which means they are not writable by the non-root user, and running RUN chown ... on those files won't work unless the current user is also root. So one ends up switching back and forth between root and the other user throughout the Dockerfile.
    • David
      David over 7 years
      So what is the approach to take if you need to switch user in the middle of a RUN command that contains a chain of unix commands? e.g. RUN start some service && su myuser && other cmds to run while service is running but need to run as myuser
    • Jan Vladimir Mostert
      Jan Vladimir Mostert over 7 years
      split the chain, that's the only way.
  • Spencer Williams
    Spencer Williams about 8 years
    I'm curious about how to make sure previously run commands are available to the user set in the Dockerfile. I have a question where folders and permissions previously set by root are not available after switching to another user with the USER instruction.
  • x-yuri
    x-yuri over 5 years
    You might need COPY --chown=myuser ... down the road.
  • Noname
    Noname almost 3 years
    How to run multiple commands as different users in a single RUN? Will RUN sudo su user && command1 && sudo su user2 && command2 work?