admin管理员组

文章数量:1405910

ReactJS Dockerfile:

FROM node:23.7.0-slim AS build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD [ "npm", "run", "build"]

Here is the docker-compose file:

services:
  watchtower:
    image: containrrr/watchtower
    command:
      - "--label-enable"
      - "--interval"
      - "30"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.docker/config.json:/config.json

  frontend:
    container_name: frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile
    image: <IMAGE_URL>
    pull_policy: always
    volumes:
      - dist:/app/dist
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

The issue is the container exists after building the app and watchtower can no longer scan for it. What production method can I use besides Nginx, I have one in docker-compose, and it also proxies reverse to the backend.

One solution I thought of is using a small HTTP server to serve the built files and then using Nginx to reverse proxy it, but I don't know if it's a good practice in a production environment.

FROM node:23.7.0-slim AS build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM node:23.7.0-slim AS serve

WORKDIR /app

RUN npm install -g http-server

COPY --from=build /app/dist /app/dist

EXPOSE 3000

CMD ["http-server", "dist", "-p", "3000"]

ReactJS Dockerfile:

FROM node:23.7.0-slim AS build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD [ "npm", "run", "build"]

Here is the docker-compose file:

services:
  watchtower:
    image: containrrr/watchtower
    command:
      - "--label-enable"
      - "--interval"
      - "30"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.docker/config.json:/config.json

  frontend:
    container_name: frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile
    image: <IMAGE_URL>
    pull_policy: always
    volumes:
      - dist:/app/dist
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

The issue is the container exists after building the app and watchtower can no longer scan for it. What production method can I use besides Nginx, I have one in docker-compose, and it also proxies reverse to the backend.

One solution I thought of is using a small HTTP server to serve the built files and then using Nginx to reverse proxy it, but I don't know if it's a good practice in a production environment.

FROM node:23.7.0-slim AS build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM node:23.7.0-slim AS serve

WORKDIR /app

RUN npm install -g http-server

COPY --from=build /app/dist /app/dist

EXPOSE 3000

CMD ["http-server", "dist", "-p", "3000"]
Share Improve this question asked Mar 7 at 8:03 Kadiem AlqazzazKadiem Alqazzaz 6611 gold badge10 silver badges31 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Compose's general expectation is that services: are long-running things that don't immediately exit. You'd set a Compose service to, say, npm run start, but not npm run build.

Multi-stage builds haven't always been in Docker, and the setup you show that tries to run a build-only container via Compose was one workaround you might find in old setups. The multi-stage build you show in the second example – RUN npm run build in an earlier stage, then COPY the built application into a more minimal image that can serve it – is a standard approach, and if you do need to run a container for this, that's a perfectly normal production-ready setup. (I might use an nginx server rather than Node and the http-server package, but it's basically the same setup.)

This is a little bit separate from what Watchtower does. The important difference is that you're build:ing the application yourself from local code, so if you want a new version of it, you can docker-compose build && docker-compose up -d yourself. If you pushed the image to a registry

services:
  frontend:
    image: registry.example/frontend  # with ...:latest or another moving tag
    # no build:

then when your CI system pushed a new image to the registry, Watchtower would automatically pull it and recreate the container.

I'll also add that there are no volumes: in this setup. Your code and library stack is contained entirely in the image. For Node applications especially, there are some common hacks around the node_modules tree, but these result in code being stored in a Docker volume that will take precedence over what's in the image. If you had a volume mount over node_modules, and Watchtower pulled a newer image, you would get the old modules tree from the volume and not the updates in the image. You don't usually want that behavior.

本文标签: