I'm trying to get a basic nodeJs and postgres system up and running but for some reason the node container keeps receiving a SIGTERM signal and shutting down only to be started back up due to the restart policy and then shutdown again. The cycle goes on and on.
What am I missing here? I ran the same code in non-swarm mode and it worked fine, the container was healthy and stayed up. One more thing I did notice during swarm mode is that inspite of asking docker to keep 1 replica, the docker stack services service_name
always returns 0/1 replicas
Posting my dockerfile
and docker-compose.yml
file here
# BASE stage
FROM node:14-alpine as base
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install --frozen-lockfile --prod
FROM node:14-alpine
ENV NODE_ENV development
ENV VERSION V1
WORKDIR /usr/src/app
RUN apk --no-cache add curl
COPY src src/
# Other copy commands
COPY --from=base /usr/src/app/node_modules /usr/src/app/node_modules
# check every 5s to ensure this service returns HTTP 200
HEALTHCHECK --interval=5s --timeout=3s --start-period=10s --retries=3 \
CMD curl -fs http://localhost/health
ENTRYPOINT [ "node", "src/index.js" ]
version: "3.7"
services:
api:
image: demo/hobby:v1
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
window: 120s
rollback_config:
parallelism: 1
delay: 20s
order: start-first
update_config:
parallelism: 1
delay: 1s
failure_action: rollback
order: start-first
env_file:
- ./.env
ports:
- target: 9200
published: 80
mode: host
networks:
- verse
postgres:
image: "postgres:12.3-alpine"
container_name: "test-db-dev"
networks:
- verse
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_USER=${DB_USER}
expose:
- "5432"
ports:
- "5432:5432"
restart: "unless-stopped"
networks:
verse:
driver: overlay
external: false
I assume that your container is being killed every 30 seconds. If this is true, then this is the cause:
The HEALTHCHECK
is trying to curl http://localhost/health (defaults to port 80).
Although you expose the app to the host on port 80
, the HEALTHCHECK
is performed from the container perspective, where no service is listening on that port.
Assuming that your node app is listening on port 9200 and that a GET
performed on /health
returns status 200
, the Dockerfile
should be built like this:
[...]
HEALTHCHECK --interval=5s --timeout=3s --start-period=10s --retries=3 \
CMD curl -fs http://localhost:9200/health
[...]