Search code examples
dockerdocker-composecreate-react-app

Docker COPY on multistage build doens't working


I'm using multistage build to compile an react app. Primarily I use a base node image, after I use a nginx image to expose to the port 80.

I'm attempting to COPY the build files from builder stage to the /usr/share/nginx/html folder, but gets nothing.

Building the image alone it's working, with docker-compose does nothing.

I attempted to open an issue on the docker repo but is closed, therefore open on the moby engine also is not a option when the podman(that's use moby engine) works well, except the compose that spawn a command as not sudoers and the build fail on the node image download.

FROM node:slim as build

WORKDIR /usr/app

COPY package.json .
COPY public public
COPY src src

RUN npm install
RUN npm run build

COPY build .

RUN rm -rf src
RUN rm -rf build

FROM nginx:latest

COPY --from=build /usr/app /usr/share/nginx/html
# RUN chown www-data:www-data ./usr/share/nginx/html/*

EXPOSE 80

On the ls command I see the build, but when I'm attempt to connect to localhost a get the forbidden error, and when attempt to access the index.html I'm getting the 404.

I entered on the the html folder using bash and verify using the namei -l . and there's no file at all.

What could I be doing wrong? I've searched a ton of questions and don't get the answer or any direction, execpt the fact of add a slash of the folder to be copied.

Currently I'm using a RHEL. So, needs sudoers permission to run docker commands. Maybe it's the problem? On podman-compose I need to spawn an sudo docker-compose build command, and it run another build commands as non root.

Therefore, this not occurs on docker-ce.


Solution

  • First of all, ensure you have a correct nginx config in the file nginx.conf. e.g:

    server {
    listen 80;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
      }
    }
    

    Second, it's not necessary run these lines:

    COPY build . # you should call directly the build folder, because there isn't any other files of build stage
    
    RUN rm -rf src #after finish build step, this image will no longer exist.
    RUN rm -rf build
    RUN ls
    

    Finally your Dockerfile should look like this

    FROM node:slim as build
    
    WORKDIR /usr/app
    
    COPY package.json .
    COPY public public
    COPY src src
    
    RUN npm install
    RUN npm run build
    
    FROM nginx:latest
    
    COPY --from=build /usr/app/build /usr/share/nginx/html
    COPY nginx.conf /etc/nginx/conf.d
    
    # if you are using react router 
    # you need to overwrite the default nginx configurations
    # remove default nginx configuration file
    RUN rm /etc/nginx/conf.d/default.conf 
    
    EXPOSE 80