Keywords: Docker | User Management | Security Practices | Container Security | Non-Privileged Users
Abstract: This article provides an in-depth exploration of best practices for creating and managing non-privileged users in Docker containers. By analyzing the differences between adduser and useradd commands, it details proper user permission configuration in Dockerfiles, including user creation, permission assignment, and security considerations. With concrete code examples, the article explains the importance of running container processes as non-root users and offers comprehensive implementation solutions.
Problem Background and Challenges
In Docker containerized deployments, process permission management is a critical security consideration. Many developers encounter interactive prompts when creating users in Ubuntu-based images. When attempting to use the adduser command in Dockerfiles, the system waits for password input and other user information, causing build process interruptions.
Core Solution: The useradd Command
The key to solving this issue lies in using the non-interactive useradd command instead of adduser. useradd is the underlying Linux tool for user creation, supporting direct configuration of all user attributes through command-line parameters, thus avoiding interactive prompts.
The basic user creation command is as follows:
RUN useradd -ms /bin/bash newuser
Parameter explanations:
-m: Automatically creates the user's home directory-s /bin/bash: Sets the user's default shell to bash- This command creates a complete user environment, including home directory and default configuration files
Complete Dockerfile Configuration
The complete process for configuring non-privileged users in Dockerfiles includes user creation, permission settings, and working directory configuration:
# Create uwsgi user
RUN useradd -ms /bin/bash uwsgi
# Create celery user
RUN useradd -ms /bin/bash celery
# Create shared worker group
RUN groupadd worker && usermod -aG worker uwsgi && usermod -aG worker celery
# Switch to non-privileged user
USER uwsgi
# Set working directory
WORKDIR /home/uwsgi
Permission Management and Security Practices
Running processes with non-privileged users in Docker containers has significant security implications:
Security Advantages:
- Limits the permission scope of processes within containers
- Reduces potential security risks
- Adheres to the principle of least privilege
- Prevents privilege escalation attacks
Permission Configuration Considerations:
- Ensure users have appropriate read/write permissions for required files and directories
- For operations requiring special privileges, temporarily switch back to root user in Dockerfile
- Using explicit UIDs and GIDs avoids username resolution issues
Advanced Configuration Techniques
For more complex application scenarios, the following advanced configurations can be employed:
# Create system user (suitable for service accounts)
RUN useradd -r -s /bin/false appuser
# Specify specific UID and GID
RUN groupadd -g 1001 appgroup && useradd -u 1001 -g appgroup appuser
# Configure password (if needed)
RUN echo 'appuser:password' | chpasswd
Runtime User Management
Beyond build-time user configuration, users can also be specified dynamically during container runtime:
# Run container using current host user ID
docker run --user $(id -u):$(id -g) image_name
# Configure user in docker-compose
services:
app:
user: "${CURRENT_UID}"
Practical Application Example
Below is a complete uWSGI and Celery application configuration example:
FROM ubuntu:20.04
# Install necessary packages
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Create application users and groups
RUN groupadd -g 1000 worker && \
useradd -u 1000 -g worker -ms /bin/bash uwsgi && \
useradd -u 1001 -g worker -ms /bin/bash celery
# Install application dependencies
COPY requirements.txt .
RUN pip3 install -r requirements.txt
# Copy application code
COPY . /app
# Set permissions
RUN chown -R uwsgi:worker /app
# Switch to non-privileged user
USER uwsgi
# Set working directory
WORKDIR /app
# Startup command
CMD ["uwsgi", "--ini", "uwsgi.ini"]
Common Issues and Solutions
Issue 1: Insufficient Permissions
When non-privileged users cannot access certain resources, resolve with:
# Temporarily switch back to root for permission settings
USER root
RUN chown -R uwsgi:worker /path/to/directory
USER uwsgi
Issue 2: Port Binding Failure
Non-privileged users cannot bind to ports below 1024. Solutions:
- Use ports above 1024
- Handle low port mapping through reverse proxies
Security Best Practices Summary
When using non-privileged users in Docker containers, follow these best practices:
- Always explicitly specify USER instruction in Dockerfiles
- Create dedicated system users for different services
- Use explicit UIDs and GIDs to avoid dependency on username resolution
- Regularly review and update user permission configurations
- Enhance security further with user namespaces
By properly configuring non-privileged users, you can significantly improve Docker container runtime security while maintaining normal application functionality. This practice has become a standard security requirement in modern containerized deployments.