Docker-compose: nginx fails to start due to "permission denied" error

Viewed 8487

I'm trying to build gatsby + nginx containers to deploy it online.

Docker fails when executing COPY from the gatsby container to the nginx container (/app/public to /usr/share/nginx/html). It says it's a permission issue, but I am doing a chown nginx:nginx (assigning ownership to nginx user). Anything else I'm missing?

web-nginx | nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

Questions

  • What are some debugging techniques for this kind of error?
  • I added RUN id and RUN ls -l -d to inspect current users in the filesystem. There is no nginx user, why is that?
Step 11/18 : RUN ls -l -d
 ---> Using cache
 ---> 5f25d03e4a5f
Step 12/18 : RUN id
 ---> Running in 9c9e6ae0bb56
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

Here's the Dockerfile:

# Stage 1: Build gatsby website
FROM node:alpine AS build

RUN \
  apk add --no-cache python make g++ && \
  apk add vips-dev fftw-dev --update-cache \
  --repository http://dl-3.alpinelinux.org/alpine/edge/community \
  --repository http://dl-3.alpinelinux.org/alpine/edge/main \
  && rm -fR /var/cache/apk/*

RUN npm install -g gatsby-cli

WORKDIR /app
COPY ./package.json .
RUN yarn install && yarn cache clean
COPY . .
CMD ["yarn", "build", "-H", "0.0.0.0" ]

# Stage 2: Serve the site
FROM nginx:alpine

COPY nginx /etc/nginx/
RUN chown nginx:nginx /usr/share/nginx/html
COPY --from=build /app/public /usr/share/nginx/html
RUN touch /var/run/nginx.pid && chown nginx:nginx /var/run/nginx.pid

USER nginx

EXPOSE 8080
HEALTHCHECK CMD [ "wget", "-q", "localhost:8080" ]

But then I get an error:

Creating web-nginx ... done
Attaching to web-nginx
web-nginx | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web-nginx | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web-nginx | 10-listen-on-ipv6-by-default.sh: Can not modify /etc/nginx/conf.d/default.conf (read-only file system?), exiting
web-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
web-nginx | 2020/06/04 07:15:17 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
web-nginx | nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
web-nginx exited with code 1

What I tried...

  • removing the COPY --from=build... part to RUN cp -r ./app/public /usr/share/nginx/html, but that gives a ./app/public directory does not exist error. I'm assuming that's because the nginx stage doesn't have access to the other container.
  • changing it to root user by adding USER root before the COPY statement.

docker-compose.yml, just in case:

version: '3'

services:
  web:
    build: '.'
    image: 'my-gatsby-website'
    container_name: 'web-nginx'
    restart: 'unless-stopped'
    ports:
      - '8080:8080'
    volumes:
      - /app/node_modules
      - .:/app
    environment:
      - NODE_ENV=production
      - GATSBY_WEBPACK_PUBLICPATH=/

Help!

1 Answers

I got it working!

What I did to fix it

  • I removed the chown command altogether. I think it was throwing a permission denied error because the nginx user did not exist in the container at compile time, making the chown command invalid (when changing file ownership, that user/group needs to exist beforehand). Not sure why that line was needed (I got it from a blog post somewhere)...

I realize I'm copying the build directory as root user, which is not ideal. Please let me know if there's a better way to do this.

Run docker-compose up --build. The app should be accessible in localhost:8080 from the host.

Hope this helps someone.

Final dockerfile

# Stage 1: Build Gatsby
FROM node:alpine AS build

RUN \
  apk add --no-cache python make g++ && \
  apk add vips-dev fftw-dev --update-cache \
  --repository http://dl-3.alpinelinux.org/alpine/edge/community \
  --repository http://dl-3.alpinelinux.org/alpine/edge/main \
  && rm -fR /var/cache/apk/*

RUN npm install -g gatsby-cli

WORKDIR /app
COPY ./package.json .
RUN yarn install && yarn cache clean
# RUN yarn cache clean && yarn install
COPY . .
CMD ["yarn", "build", "-H", "0.0.0.0" ]

# Stage 2: Serve the site
FROM nginx:mainline-alpine
RUN rm /usr/share/nginx/html/*
COPY --from=build /app/public /usr/share/nginx/html/
RUN ls usr/share/nginx/html -l

docker-compose.yml

version: '3'

services:
  web:
    build: '.'
    depends_on:
      - 'database'
    image: 'webserver-test'
    container_name: 'nginx-webserver'
    # restart: 'unless-stopped'
    ports:
      - '8080:80'
    volumes:
      - /app/node_modules
      - .:/app
    environment:
      - NODE_ENV=production
      - GATSBY_WEBPACK_PUBLICPATH=/
Related