Running a Docker Container with a Custom Non-Root User: Syncing Host and Container Permissions
Tags: docker, containers, security, devops
Published: 2023-03-29 19:52:02


![Containers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvhic3eq1tzpxdigvtax.jpg)
## Introduction
Docker has become a popular platform for developers to create, deploy, and run applications in a portable, consistent environment.  

By default, Docker containers run as the root user, which can pose security risks if the container becomes compromised. 
Also, running as root can be an issue when sharing folders between the host and the docker container.  

To reduce these risks, we'll discuss running a Docker container with a custom non-root user that matches your host Linux user's user ID (`UID`) and group ID (`GID`), ensuring seamless permission handling for mounted folders.

Running a docker build command that uses (mainly) a non-root user might force us to use `sudo` for some commands.
The same is valid for running the docker itself using unattended scripts.
You may need elevated privileges for specific tasks. 
Granting password-less sudo permissions to a non-root user allows you to perform administrative tasks without the risk of running the entire container as the root user.

Here are the steps to create and run a Docker container with a non-root user and password-less sudo permissions:
  

## Step 1: Adjust the Dockerfile to Accept UID and GID as Arguments

Modify your Dockerfile to accept the host's UID and GID as arguments. This way, you can create a user in the container with a matching UID and GID.
Add the following lines to your Dockerfile:

```Dockerfile
FROM ubuntu
ARG UID
ARG GID

# Update the package list, install sudo, create a non-root user, and grant password-less sudo permissions
RUN apt update && \
    apt install -y sudo && \
    addgroup --gid $GID nonroot && \
    adduser --uid $UID --gid $GID --disabled-password --gecos "" nonroot && \
    echo 'nonroot ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

# Set the non-root user as the default user
USER nonroot
```


## Step 2: Set the Working Directory

Set the working directory where the non-root user can access it. Add the following line to your Dockerfile:
```Dockerfile
# Set the working directory
WORKDIR /home/nonroot/app
```
This sets the working directory to '/home/nonroot/app', where the non-root user has read and write permissions.



## Step 3: Copy Files and Set Permissions

Ensure the non-root user has the necessary permissions to access the copied files. Add the following lines to your Dockerfile:

```Dockerfile
# Copy files into the container and set the appropriate permissions
COPY --chown=nonroot:nonroot . /home/nonroot/app
RUN chmod -R 755 /home/nonroot/app
```


## Step 4: Build and Run the Docker Container with UID and GID Parameters

Now you can build the Docker image and run the container with the custom non-root user. Pass your host's UID and GID as build arguments to create a user with matching permissions.
Use the following commands to build and run your container:
```bash
# Get your host's UID and GID
export HOST_UID=$(id -u)
export HOST_GID=$(id -g)

# Build the Docker image
docker build --build-arg UID=$HOST_UID --build-arg GID=$HOST_GID -t your-image-name .

# Run the Docker container
docker run -it --rm --name your-container-name your-image-name id
```
The docker output will be:
`uid=1000(nonroot) gid=1000(nonroot) groups=1000(nonroot)`


## Optional - Adding Docker Compose for Running a Custom Non-Root User Container

Docker Compose is a tool for defining and running multi-container applications using a YAML file to configure the application's services, networks, and volumes. 
It simplifies managing containers, especially when working with multiple services. 
This section will discuss how to use Docker Compose to run a Docker container with a custom non-root user that matches your host's UID and GID.
Create a `docker-compose.yml` file in your project directory with the following content:

```yaml
version: '3.8'

services:
  your_service_name:
    build:
      context: .
      args:
        UID: ${HOST_UID}
        GID: ${HOST_GID}
    image: your-image-name
    container_name: your-container-name
    volumes:
      - ./app:/home/nonroot/app
```

This YAML file defines a service, `your_service_name`, using the Dockerfile in the current directory. The `build` section passes the `UID` and `GID` build arguments from the host environment variables `HOST_UID` and `HOST_GID`. The `volumes` section maps a local directory (`./app`) to the container's working directory (`/home/nonroot/app`), ensuring seamless permission handling for the mounted folder.


First, to run the container using Docker Compose set the `HOST_UID` and `HOST_GID` environment variables in your host system.
The following command will build the docker (if needed), start it, print the user ID, and remove the container:
```bash
HOST_UID=$(id -u) HOST_GID=$(id -g) docker compose run --rm your_service_name id
```

## Conclusion
Running a Docker container with a custom non-root user that matches your host's UID and GID ensures seamless permission handling for mounted folders while maintaining security. 
Optimizing the Dockerfile and combining RUN commands can reduce the image size and improve performance. Following these steps will help you create and run a Docker container with a non-root user that aligns with your host's permissions, reducing the risk of potential security breaches and permission issues. Always prioritize security when deploying applications and containers to ensure a safe and stable environment.

Integrating Docker Compose into your workflow simplifies container management and improves the overall development experience, allowing you to focus on building your application.