Docker automatic code update

I am working on a Nest.js project which uses Nginx as a load balance, Redis for session management, and it connects to Postgres database. I want a situation whereby if I make changes to my codebase my docker container should update itself without me having to kill and restart the service. Find below my Dockerfile and docker-compose.yml content

Dockerfile

# Development stage
FROM node:18.18.2-slim AS development

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install --only=development

COPY . .

RUN npm run build

# Production stage
FROM node:18.18.2-slim AS production

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install --only=production

COPY . .

COPY --from=development /usr/src/app/dist ./dist

# CMD ["node", "dist/main"]
CMD [ "npm", "run", "start:dev" ]
docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:latest
    ports:
      - '8080:80'
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - docker-network

  db:
    container_name: lagbaja-db
    image: postgres:14.7 # match with the latest PostgreSQL version supported by AWS Aurora
    restart: always
    ports:
      - '5433:5432' # specify port forwarding
    environment:
      - POSTGRES_USER=lagbaja
      - POSTGRES_PASSWORD=la2024
      - POSTGRES_DB=lagbaja
    networks:
      - docker-network

  dev:
    image: lagbaja-api-dev:1.0.0
    build:
      context: .
      target: development
      dockerfile: ./Dockerfile
    command: npm run start:dev
    ports:
      - '3000'
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules
    # volumes:
    #   - .:/usr/src
    #   - /usr/node_modules
    restart: always
    environment:            # Add environment variables for the app
      - DATABASE_HOST=db 
    depends_on:
      - db
      - redis
    networks:
      - docker-network

  redis:
    image: 'redis:latest'
    ports:
      - '6379'
    restart: unless-stopped
    networks:
      - docker-network

networks:
  docker-network:
    driver: bridge

Thanks guys

I recommend reading about compose watch

It depends :sweat_smile:

If you bind mount your sources into the container, you can use nodemon to restart node within container upon code update.

If you have a build process in place, you can probably use something like watchtower to update (replace) the running container on new image.

For compose use, check @rimelek s previous answer.

Thanks @rimelek. I was able to set the watch but nothing seems to happen when I save file changes. Here are my updated Dockerfile and docker-compose.yml

Dockerfile

# Development stage
FROM node:18.18.2-slim AS development

WORKDIR /usr/src/app

# Install nodemon globally
# RUN npm install -g nodemon

COPY package*.json ./

RUN npm install --only=development
# RUN npm install -g @nestjs/cli

COPY . .

RUN npm run build

# Production stage
FROM node:18.18.2-slim AS production

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install --only=production

# RUN npm install pm2 -g
# RUN npm install -g @nestjs/cli

COPY . .

COPY --from=development /usr/src/app/dist ./dist

CMD ["node", "dist/main"]
# CMD ["nodemon", "--watch", "src", "--exec", "ts-node", "dist/main"]
# CMD [ "npm", "run", "start:dev" ]

docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:latest
    ports:
      - '8080:80'
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - docker-network

  db:
    container_name: lagbaja-db
    image: postgres:14.7 # match with the latest PostgreSQL version supported by AWS Aurora
    restart: always
    ports:
      - '5433:5432' # specify port forwarding
    environment:
      - POSTGRES_USER=lagbaja
      - POSTGRES_PASSWORD=la2024
      - POSTGRES_DB=lagbaja
    networks:
      - docker-network

  dev:
    image: lagbaja-api-dev:1.0.0
    build:
      context: .
      target: development
      dockerfile: ./Dockerfile
    command: npm run start:dev
    
    ports:
      - '3000'
    # volumes:
    #   - .:/usr/src/app
    #   - /usr/src/app/node_modules
    # restart: always
    environment:            # Add environment variables for the app
      - DATABASE_HOST=db 
    depends_on:
      - db
      - redis
    networks:
      - docker-network
    develop:
      watch:
        - action: sync
          path: ./scr
          target: /user/src/app
          ignore:
            - node_modules/
        - action: rebuild
          path: package.json

  redis:
    image: 'redis:latest'
    ports:
      - '6379'
    restart: unless-stopped
    networks:
      - docker-network

networks:
  docker-network:
    driver: bridge
this is my VS code terminal

$ docker-compose watch
[+] Building 0.0s (0/0)                                                     docker:default
[+] Running 4/4
 ✔ Container lagbaja-db           Started                                             0.0s 
 ✔ Container api-lagbaja-redis-1  Started                                             0.0s 
 ✔ Container api-lagbaja-nginx-1  Started                                             0.0s 
 ✔ Container api-lagbaja-dev-1    Started                                             0.0s 
watching [C:\Forge\lagbaja\api-lagbaja\scr C:\Forge\lagbaja\api-lagbaja\package.json]

Typo?

Wrong command for production image?

I don’t understand what you mean.

Are you watching the correct path for changes?

Yes, I am. You can see from my VS code terminal log

watching [C:\Forge\lagbaja\api-lagbaja\scr C:\Forge\lagbaja\api-lagbaja\package.json]

Thanks for pointing this out. I made changes to the package.json flie and it triggered a rebuild. So, why isn’t it watching my src folder? I’ll do some tinkering and revert

Because you wrote scr not src.

Thanking you so much for pointing that out. I had gone through those lines severally and didn’t notice it :sweat_smile:

@bluepuma77 it is syncing file changes now but I don’t see the changes when I call the modified endpoint

Syncing dev after changes were detected:
  - C:\Forge\lagbaja\api-lagbaja\src\api\post\post.service.ts
Syncing dev after changes were detected:
  - C:\Forge\lagbaja\api-lagbaja\src\api\post\post.service.ts
Syncing dev after changes were detected:
  - C:\Forge\lagbaja\api-lagbaja\src\api\post\post.service.ts
Syncing dev after changes were detected:
  - C:\Forge\lagbaja\api-lagbaja\src\api\post\post.service.ts
  - C:\Forge\lagbaja\api-lagbaja\src\api\post\post.controller.ts

it is syncing file changes now but I don’t see the changes when I call the modified endpoint

Read about the different available actions (doc).

You probably need “sync+restart” or need to run something like nodemon inside container to restart the node process upon file change.

Update: you use typescript so you need to run the full build process (npm run build) to create updated JS files for node to run.

Ok. Thanks I’ll try this out :+1: