How to Add Users to a Docker Container
Master Docker user management by learning how to create users, assign permissions, and implement security best practices in containers.
By default, Docker containers run as root. That’s fine for quick tests but bad for production. This guide shows you how to add users properly.
Three ways to handle this:
- Dockerfile - Create users at build time (recommended)
- Runtime - Add users to running containers (temporary)
- User mapping - Match host and container users (for permissions)
Let’s go through each one.
Why Bother?
Running as root in containers is risky:
- Security: If the app gets compromised, the attacker has root
- Permissions: Writing files as root messes up host permissions
- Best practice: Least privilege principle applies here too
Bottom line: Production containers should not run as root.
Method 1: Create Users in Dockerfile
Best practice is to set up users when building the image.
Basic User Creation
FROM ubuntu:20.04
# Create a non-root user
RUN useradd -m -s /bin/bash appuser
# Switch to the new user
USER appuser
# Set working directory
WORKDIR /home/appuser
Advanced User Setup
FROM ubuntu:20.04
# Update package list
RUN apt-get update && apt-get install -y sudo
# Create user with specific UID/GID
RUN groupadd -r appgroup --gid=1001 && \
useradd -r -g appgroup --uid=1001 --shell=/bin/bash --create-home appuser
# Add user to sudo group (if needed)
RUN usermod -aG sudo appuser
# Set password (for development only)
RUN echo 'appuser:password' | chpasswd
# Switch to non-root user
USER appuser
WORKDIR /home/appuser
Key Commands Explained
| Command | Purpose | Example |
|---|---|---|
useradd -m | Create user with home directory | useradd -m john |
groupadd | Create user group | groupadd developers |
usermod -aG | Add user to group | usermod -aG sudo john |
USER | Set default user for container | USER appuser |
Some other docker articles that can help you in your docker journey:
- Copy Multiple Files in One Layer Using a Dockerfile
- Install Docker & Docker-compose for Ubuntu ARM
- Redirect Docker Logs to a Single File
- Environment Variables ARG and ENV in Docker
Method 2: Add Users at Runtime
Sometimes you need to create users in an already running container. Not recommended for production, but useful for debugging.
Create User in Running Container
# Enter the container
docker exec -it container_name bash
# Create user inside container
useradd -m -s /bin/bash newuser
# Set password
passwd newuser
# Add to sudo group (if needed)
usermod -aG sudo newuser
# Switch to new user
su - newuser
Using Docker Exec with Specific User
# Run commands as specific user
docker exec -it --user newuser container_name bash
# Or run single commands
docker exec --user newuser container_name whoami
Method 3: Map Host Users to Container
When you mount volumes, file ownership can get messy. This method keeps host and container permissions in sync.
User ID/Group ID Mapping
FROM ubuntu:20.04
# Create user with specific UID/GID that matches host user
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN groupadd -g $GROUP_ID appgroup && \
useradd -u $USER_ID -g $GROUP_ID -m -s /bin/bash appuser
USER appuser
Build with host user IDs:
docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t myapp .
Docker Compose User Mapping
version: '3.8'
services:
app:
build: .
user: "${UID}:${GID}"
volumes:
- .:/app
environment:
- USER_ID=${UID}
- GROUP_ID=${GID}
Run with:
UID=$(id -u) GID=$(id -g) docker-compose up
Best Practices
1. Never Run as Root in Production
# Good
FROM ubuntu:20.04
RUN useradd -m appuser
USER appuser
# Bad - root by default
FROM ubuntu:20.04
2. Use Specific UID/GID
Avoid permission headaches with mounted volumes:
RUN groupadd -g 1001 appgroup && \
useradd -u 1001 -g appgroup -m appuser
USER appuser
3. Use Multi-Stage Builds
Build as root, run as user:
# Build stage
FROM ubuntu:20.04 as builder
RUN apt-get update && apt-get install -y build-essential
COPY . /src
WORKDIR /src
RUN make build
# Runtime stage
FROM ubuntu:20.04
RUN useradd -m appuser
USER appuser
COPY --from=builder /src/app /home/appuser/app
4. Set File Ownership
Use COPY --chown to avoid permission issues:
COPY --chown=appuser:appuser app/ /home/appuser/app/
USER appuser
Quick Checklist
| ✅ Do | ❌ Don’t |
|---|---|
| Create dedicated users | Run as root in production |
| Set specific UID/GID | Use random UIDs |
| Set proper ownership | Use 777 permissions |
| Test before deploying | Assume it just works |
Quick Reference
Common User Creation Commands
# Create user with home directory
useradd -m -s /bin/bash username
# Create user with specific UID/GID
useradd -u 1001 -g 1001 -m username
# Add user to group
usermod -aG groupname username
# Change file ownership
chown -R username:groupname /path/to/files
Dockerfile User Examples
# Simple non-root user
FROM ubuntu:20.04
RUN useradd -m appuser
USER appuser
# User with sudo access
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y sudo
RUN useradd -m -s /bin/bash appuser
RUN usermod -aG sudo appuser
USER appuser
# User with specific UID/GID
FROM ubuntu:20.04
RUN groupadd -g 1001 appgroup && \
useradd -u 1001 -g appgroup -m appuser
USER appuser
TL;DR
- Always create non-root users for production containers
- Use specific UID/GID to avoid permission issues with volumes
- Set file ownership with
COPY --chown - Test before deploying - run
whoamiand check permissions
Start simple. Create a non-root user in your Dockerfile. Worry about namespaces and advanced security later.