i have some problem with updating && rebuiling my code base
I use this command, but it's doesn't update my code base
docker compose up --build -d --force-recreate
I tried before compose up use this command for clear data
docker compose down -v --rmi all --remove-orphans
and this works good. How can i use docker compose up without removing all data and etc everytime before building (docker-nextjs container)?
Docker version 24.0.5, build ced0996
Dockerfile
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
# set hostname to localhost
ENV HOSTNAME "0.0.0.0"
CMD ["node", "server.js"]
docker-compose.yml
version: '3'
services:
nextjs-app:
build:
context: .
dockerfile: Dockerfile
container_name: docker-nextjs
restart: always
environment:
NODE_ENV: production
volumes:
- nextjs-app-build:/app # Named volume for nextjs-app build folder
ports:
- '3000:3000'
networks:
- nginx_network
nginx:
image: csrinu236/medium-nginx-app # Placeholder for pushing image to Dockerhub
build:
context: ./nginx-docker
dockerfile: Dockerfile
volumes:
- nextjs-app-build:/app # Mount the named volume to Nginx's /app/build
depends_on:
- nextjs-app
restart: always
ports:
- '80:80'
- '443:443'
command: ['sh', '/etc/nginx/convert-nginx.sh']
networks:
- nginx_network
volumes:
nextjs-app-build: # Define the named volume
networks:
nginx_network:
external: true
Delete all of the volumes:
blocks in the file. More specifically, delete the volumes:
that are mounted over the image's /app
directory.
What's happening here is that there's an old copy of the application in the nextjs-app-build
named volume. You are successfully rebuilding the image, but then you're mounting the volume over its contents, and the contents of the named volume just outright replace what's in the rebuilt image.
It looks like you're trying to take advantage of a specific behavior of specificially Docker named volumes to share files from one container to the other. When you mount a Docker named volume to a container (and only a Docker named volume, not a bind mount or a Kubernetes PersistentVolumeClaim or anything else), the first time the volume is used (and only if the volume is totally empty), contents from the image are copied into the volume. This causes the first image's content to be copied into the volume, which is then mounted into the second container. But, if you ever update the image content, the volume doesn't update (Docker doesn't know anything about its contents and assumes it has user data of some sort) and you get this behavior.
This begs the question: how do your static assets get into the reverse proxy?
The easiest solution is to just not bother. In most reasonably modern application frameworks you can set up a static-file server in the application itself. At that point you can just forward requests to the backend, and let that deal with its own files.
# in your nginx config
location / {
proxy_pass http://nextjs-app:3000/;
# with no try_files
}
Another option is to COPY
the files into the Nginx proxy image. You could do this in the same Dockerfile, as an additional stage at the end
FROM nginx AS proxy
COPY --from=builder /app /app # (...or to /var/www/html?)
COPY ./nginx-docker/convert-nginx.sh /etc/nginx
CMD ["/etc/nginx/convert-nginx.sh"]
Then in your Compose file, you'd need to specify which part of the Dockerfile to use.
version: '3.8'
services:
build:
context: .
target: runner # <-- add
restart: always
ports:
- '3000:3000'
nginx:
image: csrinu236/medium-nginx-app # Placeholder for pushing image to Dockerhub
build:
context: . # <-- change to top-level directory (same as app)
target: proxy # <-- add
depends_on:
- nextjs-app
restart: always
ports:
- '80:80'
- '443:443'
# also note no volumes:, and using the default Compose-provided networks:
You can also COPY --from
an image name, which would let you keep the two separate Dockerfiles (assuming you're assigning an image:
name to both). The one trick with this is that Compose doesn't have a way to order image builds, so you have to manually build first the application and then the proxy.