Skip to content

Commands

Creating and Running a Container

docker run -d --name my-container nginx

List all containers
docker ps -a

List of available images
docker images

To stop the container
docker stop my-container

To run iteractively
docker run -it --name <name> <image>

To run with volume mounted for persistence
docker run -d --name <name> -v new-volume:/data <image>

Chatgpt DockerFile

FROM node:18

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]
To build the container

docker build -t my-node-app

To run

docker run -d -p 3000:3000 my-node-app

Creating a network for containers

By default, Docker containers are isolated from each other. They must be on the same network to communicate with each other. When containers are on the same network, they can resolve each other by name instead of using IP addresses. Prevents port issues and has better security.

docker network create my-network

docker run -d --name my-db --network my-network mongo
docker run -d --name my-db --network my-network node

Now, the node app can connect to MongoDB using 
mongodb://my-db:27017

Production ready Node js Dockerfile

FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production // installing production dependecies
COPY . .
RUN addgroup -S appgroup && adduser -S adduser -G appgroup=
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]

npm ci layer for faster builds, ensures clean install

Multi Stage Build for even Smaller, Faster Build

# Build Stage

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production Stage 
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

# To add the volume 
VOLUME ["/app/uploads]

# To Modify the dockerfile to exclude .env

RUN rm -f .env

# While running the container

docker run -d --env-file .env -p 3000:3000 my-node-app

# For better security, mention the read-only flag

docker run -d --read-only -p 3000:3000 my-node-app

# To improve performance by disabling dev-only features, Modify the Dockerfile

ENV NODE_ENV=production
# To run the container (Named Volume)
docker run -d -p 3000:3000 -v my-app-data:/app/uploads my-node-app

# To check the volume
docker volume ls

# For Bind Mount (Specific location)
docker run -d -p 3000:3000 -v $(pwd)/uploads:/app/uploads my-node-app

DockerFile for a react app (Without a web server)

FROM node:19.6-slim-bullseye AS base
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . . 
EXPOSE 3000
CMD ["npm", "start"]

Docker-compose.yml

version: "3.8"

services:
    frontend:
        build: ./frontend
        container_name: frontend
        restart: always
        ports: 
            - "3000:3000"
        depends_on:
            - backend
        volumes:
            - ./frontend:/app
            - /app/node_modules
    backend:
        build: .
        container_name: "container-name"
        ports:
            - "3000:3000"
        environment
            - MONGO_URI=mongodb://mongodb:27017/mydatabase
        depends_on:
            - mongodb #ensures MONGODB starts before nodejs app
        volumes: 
            - .:/app #syncs current directory with the container (any changes is reflected inside the container as well)
            - /app/node_modules #prevents overwriting node_modules inside the container
        mongodb:
            image: mongo:latest
            container_name: mongo-container
            restart: always
            ports:
                - "27017:27017"
            volumes:
                - mongo_data:/data/db # persistent Mongodb Storage
volumes:
    mongo_data: # named container to store all the collections, indexes, metadata etc, mounded it /data/db by default
docker-compose up --build

# For logs 
docker logs backend
docker logs mongo-container