Skip to content

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:

  1. 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)
  1. Nginx PID File: Nginx needs to write its PID file to /run/nginx.pid or 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)
  1. 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:

  1. For Nginx cache directories:
  2. Creating the necessary cache directories during the Docker build process
  3. Setting appropriate permissions on these directories

  4. For Nginx PID file:

  5. Creating a custom directory for the PID file during the Docker build process
  6. Setting appropriate permissions on this directory
  7. Running Nginx as root (which is required to bind to port 80)
  8. Configuring Nginx to drop privileges to the nginx user after binding

  9. For build process permissions:

  10. Using the --chown flag with COPY commands to ensure proper file ownership
  11. 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 --chown flag with COPY commands, we ensure proper file ownership for the build process

Additional Security Considerations

  • The nginx user 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 the appuser but are readable by the nginx user

Troubleshooting

If you encounter similar permission issues with Nginx in Docker containers, check:

  1. Whether Nginx is trying to write to directories it doesn't have permission to access
  2. If the container is running as a non-root user without proper directory permissions
  3. If the Nginx configuration requires writing to locations not prepared during the build process

References