5.5. Run as a Non-root User#

When we tried to build and run the container last time we got permission errors. That’s because the container user is root. This is generally a bad idea. Remember, that the container looks like a complete Linux system with its own users, that are separate from the system users outside of the container. That means we need to add users we want to exist in the Dockerfile instructions. We’ll do that in this lab.

Adding a Unix User#

The useradd command on Linux does exactly what you think it does. Let’s look at the options:

$ useradd -h 

Update the build instructions in your Dockerfile to run the useradd command, and change to the new user:

# Install packages that are required. 
RUN pip install Django==6.0.1 psutil

# Create a user 
RUN useradd -d /app -M django 

# Switch to the new user
USER django 

# Copy the Python code into the container (as the new user)
COPY --chown=django:django djangotutorial /app

# Set environment variables 
ENV PORT=8080

With all of the changes to your Dockerfile you now have a complete workable application.

Try a Build and Run#

This should work now!

$ mkdir ~/data
$ docker build -t myapp .
$ docker run -it --rm \
    -u $(id -u):$(id -g) \
    -p 8080:8080 \
    -v $HOME/data:/data \
    myapp

The Complete Dockerfile#

If you got lost and have a broken Dockerfile here’s a complete one:

# Start with the base Python container
# FIXME: Update the version
FROM docker.io/python:3.12.3

# Install packages that are required. 
RUN pip install Django==6.0.1 psutil==7.2.2

# Create a user 
RUN useradd -d /app -M django 

# Copy the Python code into the container
COPY --chown=django:django djangotutorial /app

# Set environment variables 
ENV STUDENT_NAME="No Name"
ENV SITE_NAME="www.cis-92.com"
ENV SECRET_KEY="fixme-12345"
ENV DEBUG=1
ENV DATA_DIR="/data"
ENV PORT=8080 
ENV DJANGO_SUPERUSER_NAME="test"
ENV DJANGO_SUPERUSER_EMAIL="test@test.test"
ENV DJANGO_SUPERUSER_PASSWORD="test"

# Create the data directory
RUN mkdir $DATA_DIR && chown django:django $DATA_DIR 

# Switch to the new user
USER django 

# Set the working directory
WORKDIR /app 

# Default command to execute in the container
CMD ["/bin/sh", "-c", "./start.sh"]