+20

Dockerfile for React

Hướng dẫn viết Dockerfile cho React. Một cho môi trường dev và một cho production.

DevOps VN

Môi trường Dev

Thông thường khi ta làm việc với một source code React có sẵn. Ta cần phải cài NodeJS và dùng npm để install node_modules.

Để thuận tiện cho môi trường dev trên các máy tính khác nhau (ví dụ như có bạn cài NodeJS 18, có bạn thì xài NodeJS 20). Ta có thể dùng Docker và viết Dockerfile cho môi trường dev. Để khi có bạn mới vào ta chỉ cần chạy câu lệnh docker là xong, không cần làm gì phức tạp cho việc cấu hình môi trường dev.

Viết Dockerfile cho môi trường dev. Tạo một tệp tin tên là Dockerfile.dev:

FROM node:20
 
WORKDIR /usr/src/app
 
COPY package*.json ./
 
RUN npm install
 
COPY . .
 
EXPOSE 3000
 
CMD [ "npm", "start" ]

Tạo tệp tin tên là docker-compose-dev.yaml:

version: '3.7'

services:
  frontend:
    container_name: frontend
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - './:/app'
      - '/app/node_modules'
    ports:
      - 3000:3000

Tạo tệp tin .dockerignore để bỏ các thư mục không cần thiết:

node_modules
npm-debug.log
build
.git
*.md
.gitignore

Khi có bạn mới vào làm dự án, các bạn chỉ cần clone source code về và chạy câu lệnh sau:

docker compose -f docker-compose-dev.yaml up -d

Nếu bạn có sửa gì lại Dockerfile.dev thì chỉ cần chạy lại với --build

docker compose -f docker-compose-dev.yaml up -d --build

Môi trường Production

Dockerfile để build Docker Image cho môi trường Production.

FROM node:20-alpine as build

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Tại sao ta lại chạy lệnh COPY package*.json ./ rồi RUN npm install, tiếp theo đó mới chạy lệnh COPY . . rồi RUN npm run build, sao không viết ngắn lại như bên dưới:

COPY . .
RUN npm install
RUN npm run build

Viết như trên phải gọn hơn không? Câu trả lời là để ta cận dụng Cache Layer khi build Docker Image:

COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

Khi ta viết như trên thì chỉ khi nào ta thay đổi package.json thì khi build Docker Image nó mới chạy lại câu lệnh npm install, còn nếu ta không thay đổi gì trong package.json thì khi build Docker Image nó sẽ bắt đầu từ câu lệnh:

COPY . .
RUN npm run build

Không cần chạy lại câu lệnh npm install, giúp ta build nhanh hơn. Cấu hình của tệp tin nginx.conf để COPY vào Dockerfile:

# auto detects a good number of processes to run
worker_processes auto;

#Provides the configuration file context in which the directives that affect connection processing are specified.
events {
    # Sets the maximum number of simultaneous connections that can be opened by a worker process.
    worker_connections 8000;
    # Tells the worker to accept multiple connections at a time
    multi_accept on;
}


http {
    # what times to include
    include       /etc/nginx/mime.types;
    # what is the default one
    default_type  application/octet-stream;

    # Sets the path, format, and configuration for a buffered log write
    log_format compression '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $upstream_addr '
        '"$http_referer" "$http_user_agent"';

    server {
        # listen on port 80
        listen 80;
        # save logs here
        access_log /var/log/nginx/access.log compression;

        # where the root here
        root /usr/share/nginx/html;
        # what file to server as index
        index index.html index.htm;

        location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to redirecting to index.html
            try_files $uri $uri/ /index.html;
        }

        # Media: images, icons, video, audio, HTC
        location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
          expires 1M;
          access_log off;
          add_header Cache-Control "public";
        }

        # Javascript and CSS files
        location ~* \.(?:css|js)$ {
            try_files $uri =404;
            expires 1y;
            access_log off;
            add_header Cache-Control "public";
        }

        # Any route containing a file extension (e.g. /devicesfile.js)
        location ~ ^.+\..+$ {
            try_files $uri =404;
        }
    }
}

Cấu trúc thư mục của ta như sau:

.
├── public
└── src
└── .dockerignore
└── Dockerfile
└── Dockerfile.dev
└── docker-compose-dev.yaml
└── nginx.conf
└── package.json
└── package-lock.json

Ngỗn ngữ khác

Docker file cho các ngôn ngữ khác ở đây: Dockerfile


Tham gia nhóm chat của DevOps VN tại Telegram hoặc Slack.

Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.