Issue
I need to build docker. I have a Makefile and two DockerFiles (first for build FE container and second for nginx). During the build process, created OUT
folder and on the compiling stage the "Static" folder created inside OUT folder. The result - docker works well.
In this case, after the build process, I need to remove OUT folder from local machine, but I can't do it without root permission. When I use command rm -rf out
in the makefile I have an error with permissions:
rm -rf out
rm: cannot remove 'out/static/css/479.0d9b8ebc.chunk.css': Permission denied
I see OUT folder created by local user and Static folder created by root user. If I add Sudo command - the folder is removed correctly, but I need to enter the user password manually each time I make a new docker.
Question: How to remove OUT folder after compilation?
Makefile:
all: react-build web-app
DOCKERTAG?='cloud-interface:latest'
GIT_VERSION := $(shell git describe --abbrev=7 --dirty --always --tags)
web-app:
echo $(GIT_VERSION) > version.html
docker build -t $(DOCKERTAG) -f nginx-container/Dockerfile .
rm -rf out
docker rmi -f frontend-temp
react-build: build-container/Dockerfile web-application
docker build -t frontend-temp -f build-container/Dockerfile .
rm -rf out
mkdir out
docker run -it -v $(shell realpath out):/usr/bin/app/build frontend-temp bash -c "npm run build"
.PHONY: clean
Dockerfile build-container:
FROM node:16.17.0-bullseye-slim
#Copy application files
RUN mkdir -p /usr/bin/app
RUN npm install -g npm
COPY web-application/ /usr/bin/app/
WORKDIR /usr/bin/app
RUN npm install --force
#CMD ["npm", "run", "build"]
EXPOSE 8080
Dockerfile nginx-container:
FROM nginx
COPY out /usr/share/nginx/html
COPY version.html /usr/share/nginx/html/version.html
COPY nginx-container/nginx.conf /etc/nginx/nginx.conf
COPY nginx-container/default.conf /etc/nginx/conf.d/default.conf
WORKDIR /usr/share/nginx/html
COPY web-application/.env .
COPY web-application/env.sh .
RUN apt-get install bash
RUN chmod +x env.sh
CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]
Solution
My default way to approach this would be with a Docker-native approach, using a multi-stage build. In a single Dockerfile, you can both build the front end and copy it into the final image. This essentially works the same way as the Makefile you show, but it doesn't depend on copying the file content out to the host system, so you don't need to delete it later.
The Dockerfile looks almost like what you have, but with the two parts concatenated together into a single Dockerfile:
FROM node:16.17.0-bullseye-slim AS build
# ^^^^^^^^ give this stage a name
# Set up the container in basically the same way
WORKDIR /usr/src/app
COPY web-application/package*.json ./
RUN npm ci
COPY web-application/ ./
# Make sure to actually build the source
RUN npm run build
# Final stage specifies the actual thing to run
FROM nginx
COPY --from=build /usr/src/app/build/ /usr/share/nginx/html/
# ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
# from the build image; using that image's filesystem path
...
With this setup you don't need to separately build the application, and the files don't exist on the host. You also don't need to give a name to the build image.
It's probably enough to use just docker build
to build the image. But if you'd prefer to wrap it into a Makefile, you only need the one block.
TAG := "latest"
IMAGE := "cloud-interface:$(TAG)"
all: .docker-build
.docker-build: version.html Dockerfile web-application/package.json
docker build -t "$(IMAGE)" .
touch "$@"
version.html:
git describe --abbrev=7 --dirty --always --tags > "$@"
clean:
rm -f version.html .docker-build
.PHONY: all clean
Your core permission problem in the original Dockerfile is that the process in the container by default runs as the root user. You can specify an alternate user when you run the container, usually like
docker run -u $(id -u) ...
Another approach is to build the image and make sure to RUN npm build
in the Dockerfile. You can then docker create
a temporary container (it does not need to actually run) and docker cp
the files out of it, at which point they will be owned by the host user.
all: .docker-web
.docker-react: build-container/Dockerfile
docker build -t frontend-temp -f build-container/Dockerfile .
touch "$@"
out/index.html: .docker-react
docker create --name built frontend-temp
rm -rf out
mkdir out
docker cp built:/usr/src/app/build/ out/
docker rm built
.docker-web: out/index.html version.html nginx-container/Dockerfile
docker build -t $(DOCKERTAG) -f nginx-container/Dockerfile .
touch "$@"
clean:
rm -f .docker-web .docker-react
rm -rf out
docker rmi frontend-temp || true
Answered By - David Maze Answer Checked By - Timothy Miller (WPSolving Admin)