Docker Nginx Permissions Guide
Overview
This guide explains how to fix permission issues with Nginx running in Docker containers, specifically addressing the error:
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
Problems
There were three permission-related issues that needed to be addressed:
- Nginx Cache Directories: When running Nginx in a Docker container as a non-root user, Nginx may not have permission to create cache directories in the default location (
/var/cache/nginx/). This results in the error:
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
- Nginx PID File: Nginx needs to write its PID file to
/run/nginx.pidor a similar location, but may not have permission to do so. This results in the error:
nginx: [emerg] open() "/run/nginx.pid" failed (13: Permission denied)
- Build Process Permissions: When running the build process as a non-root user, npm may not have permission to write to files like
package-lock.json. This results in errors like:npm error Error: EACCES: permission denied, open '/app/package-lock.json'
Solutions
The solutions involve:
- For Nginx cache directories:
- Creating the necessary cache directories during the Docker build process
-
Setting appropriate permissions on these directories
-
For Nginx PID file:
- Creating a custom directory for the PID file during the Docker build process
- Setting appropriate permissions on this directory
- Running Nginx as root (which is required to bind to port 80)
-
Configuring Nginx to drop privileges to the nginx user after binding
-
For build process permissions:
- Using the
--chownflag with COPY commands to ensure proper file ownership - Ensuring all files copied into the container are owned by the non-root user
Implementation
The following changes were made to the tracker-admin/Dockerfile and tracker-frontend/Dockerfile:
1. Nginx Cache Directories Fix
Added code to create the required Nginx cache directories with proper permissions:
# Create required nginx cache directories with proper permissions
RUN mkdir -p /var/cache/nginx/client_temp \
/var/cache/nginx/proxy_temp \
/var/cache/nginx/fastcgi_temp \
/var/cache/nginx/uwsgi_temp \
/var/cache/nginx/scgi_temp && \
chown -R nginx:nginx /var/cache/nginx && \
chmod -R 755 /var/cache/nginx
2. Nginx PID File Fix
Added code to create a custom directory for the Nginx PID file with proper permissions:
# Create directory for nginx pid file with proper permissions
RUN mkdir -p /var/run/nginx && \
chown -R nginx:nginx /var/run/nginx && \
chmod -R 755 /var/run/nginx
Modified the CMD instruction to run Nginx as root (which is required to bind to port 80):
# Start nginx - we need to run as root initially to bind to port 80,
# but nginx will drop privileges to the nginx user after binding
CMD ["nginx", "-g", "daemon off;"]
3. Build Process Permissions Fix
Used the --chown flag with COPY commands to ensure proper file ownership:
# Copy package.json and package-lock.json with proper ownership
COPY --chown=appuser:appuser package*.json ./
# Copy the rest of the application code with proper ownership
COPY --chown=appuser:appuser . .
This ensures that all files copied into the container are owned by the non-root user (appuser), allowing npm to write to files like package-lock.json during the build process.
Why This Works
- By creating the cache directories and PID file directory during the build process, we ensure they exist before Nginx tries to use them
- By setting the ownership to
nginx:nginx, we ensure the Nginx process has permission to write to these directories - By running Nginx as root initially, it can bind to port 80, and then it drops privileges to the nginx user
- By using the
--chownflag with COPY commands, we ensure proper file ownership for the build process
Additional Security Considerations
- The
nginxuser is a system user with limited privileges, which improves the security posture of the container - Running containers as non-root users is a Docker security best practice
- The static content directories (
/usr/share/nginx/html) are still owned by theappuserbut are readable by thenginxuser
Troubleshooting
If you encounter similar permission issues with Nginx in Docker containers, check:
- Whether Nginx is trying to write to directories it doesn't have permission to access
- If the container is running as a non-root user without proper directory permissions
- If the Nginx configuration requires writing to locations not prepared during the build process