User in Docker

Andrey Kopylov, our CTO, loves, actively uses and promotes Docker. In a new article, he explains how to create users in Docker. How to work with them correctly, why users should not be left with root rights and how to solve the problem of mismatching indicators in the Dockerfile.

All processes in the container will run as the root user, unless it is specified in a special way. It seems very convenient, because this user has no restrictions. That is why working as root is wrong from a security point of view. If no one in their right mind works with root rights on the local computer, then many run processes as root in containers.

There are always bugs that allow malware to get out of the container and onto the host computer. Assuming the worst, we must ensure that the processes inside the container are started by a user who does not have any rights on the host machine.

User creation

Creating a user in a container is no different from creating one in Linux distributions. However, the commands may differ for different base images.

For debian-based distributions, add to the Dockerfile:

RUN groupadd --gid 2000 node 
  && useradd --uid 2000 --gid node --shell /bin/bash --create-home node

for alpine:

RUN addgroup -g 2000 node 
    && adduser -u 2000 -G node -s /bin/sh -D node

Run processes as user

To run all subsequent processes as a user with UID 2000, run:

USER 2000

To run all subsequent processes as the node user, run:

USER node

More in documentation.

Mounting volumes

When mounting volumes inside a container, ensure that the user can read and/or write files. To do this, the UIDs (GIDs) of the user inside the container and the user outside the container that has the appropriate permissions to access the file must match. In this case, usernames do not matter.

Often on a Linux computer, a user's UID and GID are 1000. These identifiers are assigned to the first user of the computer.

Finding your IDs is easy:

id

You will receive comprehensive information about your user.
Replace 2000 from the examples with your ID and you'll be fine.

Assigning a UID and GID to a User

If the user was created earlier, but you need to change the identifiers, then you can do it like this:

RUN usermod -u 1000 node 
  && groupmod -g 1000 node

If you are using the alpine base image, then you need to install the shadow package:

RUN apk add β€”no-cache shadow

Passing the user ID inside the container when building the image

If your ID and the IDs of all the people who work on the project are the same, then it is enough to specify this ID in the Dockerfile. However, often the user IDs do not match.

How to achieve the desired is not immediately clear. For me, this was the hardest part of learning docker. Many docker users don't realize that there are different stages in the life of an image. First, the image is built using a Dockerfile for this. When running a container from an image, the Dockerfile is no longer used.

User creation must occur when the image is built. The same applies to the definition of the user under which the processes are launched. This means that we must somehow pass the UID (GID) inside the container.

To use external variables in a Dockerfile, use the directives EPS ΠΈ ARG. Detailed comparison of directives here.

Dockerfile

ARG UID=1000
ARG GID=1000
ENV UID=${UID}
ENV GID=${GID}
RUN usermod -u $UID node 
  && groupmod -g $GID node

You can pass arguments through docker-compose like this:

docker-compose

build:
  context: ./src/backend
  args:
    UID: 1000
    GID: 1000

PS To master all the intricacies of docker, it is not enough to read the documentation or articles. It takes a lot of practice, you need to get a feel for docker.

Source: habr.com

Add a comment