---
title: "How to Add Users to a Docker Container"
description: "Master Docker user management by learning how to create users, assign permissions, and implement security best practices in containers."
date: 2025-07-20
categories: ["vps"]
tags: ["docker"]
---

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:
1. **Dockerfile** - Create users at build time (recommended)
2. **Runtime** - Add users to running containers (temporary)
3. **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

```dockerfile
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

```dockerfile
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](https://www.bitdoze.com/copy-multiple-files-in-one-layer-using-a-dockerfile/)
- [Install Docker & Docker-compose for Ubuntu ARM](https://www.bitdoze.com/install-docker-ubuntu-arm/)
- [Redirect Docker Logs to a Single File](https://www.bitdoze.com/redirect-docker-logs-to-a-single-file/)
- [Environment Variables ARG and ENV in Docker](https://www.bitdoze.com/docker-env-vars/)

## 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

```bash
# 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

```bash
# 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

```dockerfile
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:
```bash
docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t myapp .
```

### Docker Compose User Mapping

```yaml
version: '3.8'
services:
  app:
    build: .
    user: "${UID}:${GID}"
    volumes:
      - .:/app
    environment:
      - USER_ID=${UID}
      - GROUP_ID=${GID}
```

Run with:
```bash
UID=$(id -u) GID=$(id -g) docker-compose up
```

## Best Practices

### 1. Never Run as Root in Production
```dockerfile
# 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:
```dockerfile
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:
```dockerfile
# 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:
```dockerfile
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
```bash
# 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
```dockerfile
# 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

1. **Always create non-root users** for production containers
2. **Use specific UID/GID** to avoid permission issues with volumes
3. **Set file ownership** with `COPY --chown`
4. **Test before deploying** - run `whoami` and check permissions

Start simple. Create a non-root user in your Dockerfile. Worry about namespaces and advanced security later.