drubb
drubb

Reputation: 15781

How to use sudo inside a docker container?

Normally, docker containers are run using the user root. I'd like to use a different user, which is no problem using docker's USER directive. But this user should be able to use sudo inside the container. This command is missing.

Here's a simple Dockerfile for this purpose:

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

Running this container, I get logged in with user 'docker'. When I try to use sudo, the command isn't found. So I tried to install the sudo package inside my Dockerfile using

RUN apt-get install sudo

This results in Unable to locate package sudo

Upvotes: 521

Views: 790838

Answers (14)

林果皞
林果皞

Reputation: 7793

Unlike accepted answer, I use usermod instead.

Assume already logged-in as root in docker, and "fruit" is the new non-root username I want to add, simply run this commands:

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

Remember to save image after update. Use docker ps to get current running docker's <CONTAINER ID> and <IMAGE>, then run docker commit -m "added sudo user" <CONTAINER ID> <IMAGE> to save docker image.

Then test with:

su fruit
sudo whoami

Or test by direct login(ensure save image first) as that non-root user when launch docker:

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

You can use sudo -k to reset password prompt timestamp:

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

Upvotes: 15

When neither sudo nor apt-get is available in the container, you can also jump into running container as root user using command:

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

Upvotes: 444

Charlie Parker
Charlie Parker

Reputation: 5201

The main idea is that you need to create user that is a root user according to the container.

Main commands:

RUN echo "bot:bot" | chpasswd
RUN adduser bot sudo

the first sends the literal string bot:bot to chpasswd which creates the user bot with the password bot, chpasswd does:

The chpasswd command reads a list of user name and password pairs from standard input and uses this information to update a group of existing users. Each line is of the format:

user_name:password

By default the supplied password must be in clear-text, and is encrypted by chpasswd. Also the password age will be updated, if present.

The second command I assume adds the user bot as sudo.

Full docker container to play with:

FROM continuumio/miniconda3
# FROM --platform=linux/amd64 continuumio/miniconda3

MAINTAINER Brando Miranda "[email protected]"

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    ssh \
    git \
    m4 \
    libgmp-dev \
    opam \
    wget \
    ca-certificates \
    rsync \
    strace \
    gcc \
    rlwrap \
    sudo

# https://github.com/giampaolo/psutil/pull/2103

RUN useradd -m bot
# format for chpasswd user_name:password
RUN echo "bot:bot" | chpasswd
RUN adduser bot sudo

WORKDIR /home/bot
USER bot
#CMD /bin/bash

Upvotes: 7

ABHISHEK KAMBLE
ABHISHEK KAMBLE

Reputation: 9

I'm using an Ubuntu image, while using the docker desktop had faced this issue.

The following resolved the issue:

  1. apt-get update
  2. apt-get install sudo

Upvotes: 0

Erkan Şirin
Erkan Şirin

Reputation: 2095

An example Dockerfile for Centos7. In this example we add prod_user with privilege of sudo.

FROM centos:7

RUN yum -y update && yum clean all

RUN yum -y install openssh-server  python3 sudo

RUN adduser -m prod_user && \
    echo "MyPass*49?" | passwd prod_user --stdin && \
    usermod -aG wheel prod_user && \
    mkdir /home/prod_user/.ssh && \
    chown prod_user:prod_user -R  /home/prod_user/ && \
    chmod 700 /home/prod_user/.ssh

RUN echo "prod_user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers

RUN echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config

RUN systemctl enable sshd.service

VOLUME [ "/sys/fs/cgroup" ]

ENTRYPOINT ["/usr/sbin/init"]

Upvotes: 2

Chris
Chris

Reputation: 6382

For anyone who has this issue with an already running container, and they don't necessarily want to rebuild, the following command connects to a running container with root privileges:

docker exec -ti -u root container_name bash

You can also connect using its ID, rather than its name, by finding it with:

docker ps -l

To save your changes so that they are still there when you next launch the container (or docker-compose cluster) - note that these changes would not be repeated if you rebuild from scratch:

docker commit container_id image_name

To roll back to a previous image version (warning: this deletes history rather than appends to the end, so to keep a reference to the current image, tag it first using the optional step):

docker history image_name
docker tag latest_image_id my_descriptive_tag_name  # optional
docker tag desired_history_image_id image_name

To start a container that isn't running and connect as root:

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

To copy from a running container:

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

To export a copy of the image:

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

Which you can restore to another Docker install using:

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

It is much quicker but takes more space to not compress, using:

docker save container | dir/file.tar

And:

cat dir/file.tar | docker load

Upvotes: 91

Animesh
Animesh

Reputation: 74

There is no answer on how to do this on CentOS. On Centos, you can add following to Dockerfile

RUN echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \
    chmod 0440 /etc/sudoers.d/user

Upvotes: 0

M. Scott Ford
M. Scott Ford

Reputation: 2989

The other answers didn't work for me. I kept searching and found a blog post that covered how a team was running non-root inside of a docker container.

Here's the TL;DR version:

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 

I was using FROM node:9.3 for this, but I suspect that other similar container bases would work as well.

Upvotes: 154

Alex Kaszynski
Alex Kaszynski

Reputation: 1986

This may not work for all images, but some images contain a root user already, such as in the jupyterhub/singleuser image. With that image it's simply:

USER root
RUN sudo apt-get update

Upvotes: 7

Yogi Ghorecha
Yogi Ghorecha

Reputation: 1748

If SUDO or apt-get is not accessible inside the Container, You can use, below option in running container.

docker exec -u root -it f83b5c5bf413 ash

"f83b5c5bf413" is my container ID & here is working example from my terminal:

enter image description here

Upvotes: 12

Seth Bergman
Seth Bergman

Reputation: 426

Here's how I setup a non-root user with the base image of 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

What happens with the above code:

  • The user and group foo is created.
  • The user foo is added to the both the foo and sudo group.
  • The uid and gid is set to the value of 999.
  • The home directory is set to /home/foo.
  • The shell is set to /bin/bash.
  • The sed command does inline updates to the /etc/sudoers file to allow foo and root users passwordless access to the sudo group.
  • The sed command disables the #includedir directive that would allow any files in subdirectories to override these inline updates.

Upvotes: 11

XtraSimplicity
XtraSimplicity

Reputation: 6042

If you have a container running as root that runs a script (which you can't change) that needs access to the sudo command, you can simply create a new sudo script in your $PATH that calls the passed command.

e.g. In your 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

Upvotes: 2

Ismail
Ismail

Reputation: 1948

if you want to connect to container and install something
using apt-get
first as above answer from our brother "Tomáš Záluský"

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

then try to

RUN apt-get update or apt-get 'anything you want'

it worked with me hope it's useful for all

Upvotes: 25

drubb
drubb

Reputation: 15781

Just got it. As regan pointed out, I had to add the user to the sudoers group. But the main reason was I'd forgotten to update the repositories cache, so apt-get couldn't find the sudo package. It's working now. Here's the completed code:

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

Upvotes: 392

Related Questions