I am trying to containerize the front-end of my website and automate its deployment. My goal is to be able to have a new image be generated and hosted when a change is pushed, and have the server automatically fetch it and restart the container. Here are the steps that I am taking:
-
I create the image by first building my Node application and then bundling the distribution and nginx configuration files into the latest linuxserver/letsencrypt image. This is the Dockerfile:
# Use the NodeJS image as builder FROM node:alpine AS builder # Create the workspace RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # Copy the package file and source code COPY package.json /usr/src/app COPY . ./ # Install dependencies RUN npm install # Build the application RUN npm run build # The nginx server, this builds the final image FROM linuxserver/letsencrypt # Copy the nginx configuration COPY ./config/nginx.conf /config # Copy the output of the builder COPY --from=builder /usr/src/app/dist /config/www # Inform Docker to listen on port 443 and 80 EXPOSE 443 80
-
This image is uploaded to GitHub’s package registry and I poll for updates using Watchtower.
-
The image is started using this docker-compose file:
version: "3" services: ... frontend: image: [IMAGE] container_name: frontend cap_add: - NET_ADMIN environment: - PUID=1000 - PGID=1000 - TZ=[TIMEZONE] - URL=[URL] - SUBDOMAINS=www, - VALIDATION=http ports: - 443:443 - 80:80 volumes: - ./frontend:/config restart: unless-stopped ...
The issue is that the files that were packaged into the image using the COPY
instruction are being overwritten when I use the following line in my docker-compose:
volumes:
- ./frontend:/config
If I remove that section from my docker-compose file everything works fine, however this is not a solution because that folder stores important data.
I have read that mounting a volume completely overwrites any previous data, however I like the fact that I can easily load the image onto my server and have all the required files already embedded. Is there anything that I can do to fix my issue, or am I misusing/misunderstanding docker images?
I have tried setting the volume to read only as suggested here, however this did not work and instead caused the image to continually stop and restart.
I have also briefly read about bind mounts and am wondering if they will be of any use.
This behavior is expected. Docker mounts work in the same way as Linux mounts, i.e. overwriting contents of the target directory with the source directory contents.
My suggestion is to use another destination directory for your volume, e.g.
volumes:
- ./frontend:/someotherdir
And then adjust your nginx configuration to look for JS files there.
I found out that I could retain the data in the image by first creating a named volume:
volumes:
frontend_data:
And then mounting the container to that volume:
services:
frontend:
...
volumes:
- frontend_data:/config
...