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
...