+112

Dockerize project NodeJS, MongoDB, Redis, Passport

Cập nhật gần nhất: 10/11/2024

Xin chào các bạn quay trở lại với Series học Docker và.... "Rồi rồi biết rồi bài nào cũng có mỗi 1 câu chào" 😂😂

Ở bài trước chúng ta đã cùng nhau dockerize ứng dụng Laravel, hiểu được EXPOSE là gì, sự khác nhau giữa EXPOSE và MAPPING PORT, cách các container giao tiếp với nhau, cùng với đó là chút chút kiến thức về Linux và webserver(nginx)

Và ta sẽ tiếp tục series với việc Dockerize ứng dụng NodeJS, MongoDB, Redis, Passport nhé 😉.

Lí do mình tách bài này ra thành một bài riêng so với bài Dockerize ứng dụng NodeJS vì mình không muốn các bạn bị bội thực ngay từ ban đầu (mình thương người lắm 😊😊)

Bắt đầu từ bài này chúng ta sẽ thực hành nâng cao hơn chút đó là ta sẽ dockerize những project giống như lúc ta làm thật, đầy đủ các thứ như databse, redis, cấu hình cho môi trường dev và deploy, và ta sẽ thử deploy trực tiếp project nodejs ở server thật xem sao nhé 😉

Bắt đầu thôi nào

Tiền Setup

Lại tiền setup, bài nào cũng thấy tiền setup 😝😝. Vì có thể có nhiều bạn đọc trực tiếp bài này của mình mà không đọc các bài trước dẫn tới việc các bạn ấy chưa chuẩn bị sẵn "đạn dược" 💪💪

Nhớ check là các bạn đã cài Docker và Docker-compose rồi nhé. Ở thời điểm hiện tại 2025 thì Docker compose đã được tích hợp luôn vào Docker cli rồi. Nếu các bạn dùng docker bản cũ mà không có thì nhớ check lại phần cuối bài trước của mình để biết cách cài đặt nhé.

Setup project

Clone source

Vì trong series này ta tập trung vào học Docker nên với mỗi bài mình sẽ chuẩn bị sẵn cho các bạn các project, có thể chạy được không cần đến Docker, và việc của ta là dockerize các project đó.

Ở bài này các bạn clone source code ở đây nhé(nhánh master nhé các bạn)

Code cho bài này được để ở thư mục docker-node-mongo-redis, cả bài này ta chỉ làm việc với thư mục này thôi nhé

Tổng quan project

Docker node

Project này có chức năng gì:

  • Trang đăng nhập, đăng kí
  • Bên trong có thêm mới sản phẩm, liệt kê danh sách sản phẩm ứng với user đăng nhập

Project này kiến trúc có những gì:

  • Ta chỉ có 2 model là User và Product
  • Dùng MongoDB để lưu trữ dữ liệu
  • Dùng Redis để lưu trữ session của user đăng nhập
  • Để xử lý Login/Logout ta dùng PassportJS
  • Để xử lý upload file ta dùng Multer

Khá đơn giản phải không 🥰

Build docker image

Và lại như thường lệ như bao bài khác, để dockerize project ta sẽ tiến hành cấu hình Dockerfile cho project và build image nhé các bạn

Lắc não trước khi sử dụng

Trước khi bắt đầu cấu hình Dockerfile ta sẽ phân tích một chút để biết ta sẽ cần cấu hình những gì nhé

Để dockerize project này ta có thể "đút" tất cả mọi thứ vào trong 1 file Dockerfile và lát nữa sẽ có 1 container chưa môi trường có tất cả mọi thứ (từ nodejs, mongo, redis,....). Nhưng như thế sẽ không tốt, 1 container đảm nhận quá nhiều nhiệm vụ, thay vào đó ta sẽ chia nhỏ ra thành nhiều container đảm nhận các nhiệm vụ khác nhau nhé 😉

Dựa vào phần kiến trúc ta đã phân tích bên trên, ta sẽ chia project thành các phần như sau, mỗi phần sẽ tương ứng với một service ta định nghĩa ở docker-compose.yml:

  • Có MongoDB là database -> ta có service db, dùng image mongo được build sẵn
  • Có redis để lưu session của user -> ta có serivce redis, dùng image redis được build sẵn
  • Phần còn lại là serivce để chạy project nodejs của chúng ta và kết nối tới 2 service bên trên -> ta chỉ cần cấu hình dockerfile cho service này, ta gọi là app

Cấu hình Dockerfile

Lại vẫn như thường lệ, ở folder gốc ta tạo 1 file tên là Dockerfile với nội dung như sau:

FROM node:22-alpine

WORKDIR /app

COPY . .

RUN npm install

# Development
CMD ["npm", "run", "dev"]

# Production
# RUN npm install -g pm2
# CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]

Những gì có ở trên mình đã giải thích rất kĩ ở các bài trước rồi các bạn có thể xem lại mình sẽ không nói nhiều nữa nhé, chỉ có một chút khác biệt ở đây là ta sẽ chia Dockerfile thành 2 phần: 1 cho môi trường dev (lúc ta code), 1 cho phần chạy production, vì khi code ta sẽ cần code được cập nhật liên tục mỗi khi ta thay đổi từ bên ngoài, còn khi production thì không (ở bài này ta dùng nodemon để cập nhật code mỗi khi có thay đổi từ bên ngoài)

Ở trên mặc định ta build image này là ta build cho môi trường dev, cuối bài khi deploy production thì ta sẽ dùng đoạn comment bên dưới nhé 😘

Build image

Và lại vẫn như thường lệ ta dùng command sau để build image nhé:

docker build -t learning-docker/docker-node-mongo-redis:v1 .

Screenshot 2024-11-10 at 4.42.16 PM.png

Chạy project

Data persistent

Ở bài này ta có databse là MongoDB để lưu trữ dữ liệu, ta có Redis để lưu trữ session của user.

Khi ta chạy project bên trong docker container, khi container khởi động lại thì mọi thứ sẽ mất và reset lại như ban đầu, tức là data trong database sẽ mất, session của những user đang đăng nhập cũng sẽ mất.

Do đó ở bài này ta sẽ tạo ra những folder để lưu lại dữ liệu để khi container có khởi động lại thì dữ liệu của ta vẫn sẽ được lưu lại nhé (việc này tiếng anh gọi là persist data), để làm được việc đó thì ta mount những folder chứa dữ liệu này vào trong container dùng volumes nha

Ở folder gốc, các bạn tạo cho mình folder .docker (để ý dấu chấm ở đầu nhé). Trong .docker ta tạo folder data, trong data ta tạo 2 folder tên là db (cho mongodb) và redis cho redis

Screenshot 2024-11-10 at 4.41.56 PM.png

Cấu hình docker-compose

Và lại vẫn cứ như cái thường lệ để chạy project ta sẽ tạo file docker-compose.yml với nội dung như sau nhé:

version: "3.4"

services:
  app:
    image: learning-docker/docker-node-mongo-redis:v1
    volumes:
      - ./:/app # mount từ môi trường gốc vào trong để nếu các bạn thay đổi code thì bên trong sẽ tự động cập nhật
    environment: # phần này ta định nghĩa ở file .env nhé
      - DB_HOST=${DB_HOST}
      - DB_NAME=${DB_NAME}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - PORT=${PORT}
    ports:
      - "${PORT}:${PORT}" # phần này ta định nghĩa ở file .env nhé
    restart: unless-stopped
    depends_on:
        - redis
        - db
  
  db:
    image: mongo:4.4
    volumes:
      - .docker/data/db:/data/db
    restart: unless-stopped
  
  redis:
    image: redis:5-alpine
    volumes:
      - .docker/data/redis:/data
    restart: unless-stopped

Nếu các bạn đã làm qua các bài trước thì đến bài này nhìn vào bên trên các bạn sẽ thấy hiểu đúng không nào, còn không thì mình khuyến khích bạn xem lại các bài trước trong series này nhé.

Giải thích một số chỗ mới như sau

  • Ở service db cho mongodb ta dùng image tên mongo (bản chính thức, các bạn search google là ra nhé)
  • Tiếp đó ta mount volume từ folder .docker/data/db ta tạo ở phần trước vào bên trong container ở đường dẫn data/db và lát nữa khi khởi chạy Mongo sẽ tự tìm đến /data/db và load những dữ liệu vào trong database nhé
  • Sao mình lại biết được đường dẫn /data/db ở trong container mà viết ở đây, thì ở phần mô tả của image ở đây họ đã nói rõ rồi nhé
  • Điều tương tự cho service redis các bạn xem ở bên dưới nhé

Có 1 điều các bạn để ý là ờ service app chúng ta có để một trường tên là depends_on (phụ thuộc vào), ý bảo là service app sẽ phụ thuộc vào 2 service dbredis, điều này thực tế sẽ xảy ra như sau:

  • Khi chạy docker compose up thì service dbredis sẽ khởi động trước service app
  • Khi chạy docker compose up app thì đồng thời sẽ tạo ra 2 service dbredis (dù khi khởi động ta chỉ nói là "khởi động mỗi service app")
  • Khi chạy docker compose stop thì service app sẽ bị stop trước 2 service kia

Note: mặc dù service app khởi động sau service db nhưng sẽ không đảm bảo service db sẵn sàng ngay thời điểm service app khởi động và kết nối tới nhé, vì service db tốn 1 khoảng thời gian nhỏ từ lúc khởi động đến lúc sẵn sàng cho kết nối. Đó là lí do vì sao ở file app.js mình lại phải có đoạn code connectionRetry để thử kết nối từ NodeJS tới MongoDB cho tới khi nào thành công

Note tiếp: Vì bản chính thức image của Mongo không có cho Alpine (các bạn có thể tự cấu hình rồi build) nhưng ở đây mình dùng luôn image được build sẵn, image này được build dựa trên môi trường hệ điều hành Ubuntu (lát nữa khi chạy các bạn exec vào trong chạy cat /etc/os-release sẽ thấy).

Chắc bạn sẽ thắc mắc: có service thì chạy trên môi trường HĐH Alpine có service chạy trên HĐH Ubuntu, có được hay không? Thì câu trả lời là chạy bình thường như cân đường hộp sữa nhé, các bạn tưởng tượng chúng giống như kiểu API, API viết bằng NODEJS vẫn sẽ gọi được API viết bằng Python như thường, miễn là trả ra cái gì đó chung kiểu như dữ liệu JSON là được (đó là mình ví dụ thế 😁)

Chạy Project

Ổn rồi đó các bạn, bây giờ chúng ta cùng chạy project lên thôi nào. Các bạn chạy command sau:

docker compose up -d

Và....... BÙM 💣, mở trình duyệt ở địa chỉ http://localhost:3000 mà không thấy có gì:

Screenshot 2024-11-10 at 4.48.55 PM.png

Check logs app ở terminal thì in ra như sau:

Screenshot 2024-11-10 at 4.49.37 PM.png

Lỗi ở terminal báo là không tìm thấy nodemon, ta thử chui vào container và xem tại sao nhé. Các bạn chạy command sau :

docker compose exec app sh

Nhưng cũng không vào được @@, container reset liên tục.

Vấn đề của chúng ta ở đây là, khi chạy thì không có thư mục node_modules bên trong container dẫn tới việc project lỗi không chạy được và PM2 liên tục reset project của chúng ta.

Ồ, really?? Ta đã chạy npm install ở trong Dockerfile rồi cơ mà???

Giải thích: bởi vì trong quá trình dev, ta muốn sửa đổi code thì bên trong container sẽ tự động cập nhật lại, do đó ở docker-compose.yml chúng ta mount volume của service app điều này dẫn tới việc toàn bộ file từ môi trường ngoài sẽ thay thế cho toàn bộ file bên trong container, mà ở môi trường ngoài ta không hề có node_modules.

Giải pháp: ta có 2 cách như mình đã trình bày ở bài Dockerize ứng dụng VueJS, ReactJS

  • dùng container tạm thời để chạy npm install
  • dùng Anonymous volume

Và ở đây ta sẽ chọn dùng Anonymous volume nhé vì nó tiện hơn 🥰🥰

Ta update lại docker-compose.yml ở service app nha:

services:
  app:
    image: learning-docker/docker-node-mongo-redis:v1
    volumes:
      - ./:/app # mount từ môi trường gốc vào trong để nếu các bạn thay đổi code thì bên trong sẽ tự động cập nhật
      - /app/node_modules # dùng anonymous volume
    environment: # phần này ta định nghĩa ở file .env nhé
      - DB_HOST=${DB_HOST}
      - DB_NAME=${DB_NAME}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - PORT=${PORT}
    ports:
      - "${PORT}:${PORT}" # phần này ta định nghĩa ở file .env nhé
    restart: unless-stopped
    depends_on:
        - redis
        - db
  
  db:
    image: mongo:4.4
    volumes:
      - .docker/data/db:/data/db
    restart: unless-stopped
  
  redis:
    image: redis:5-alpine
    volumes:
      - .docker/data/redis:/data
    restart: unless-stopped

Ok rồi đó, các bạn restart lại project bằng cách chạy command sau:

docker compose down
docker compose up -d

# lúc khởi động Mongo DB cần vài giây để chạy nên nếu bạn quay lại trình duyệt F5 ngay lập tức thì có thể không thấy gì nhé 

Sau đó chúng ta mở trình duyệt ở địa chỉ localhost:3000 (cổng 3000 ta khai báo ở file .env nhé), nếu thấy như sau là oke rồi đó 💪

Docker node

Các bạn tự nghịch xem sao nhé, thử quay lại code sửa một chỗ nào đó (sửa HTML là nhanh nhất) và F5 lại trình duyệt là các bạn sẽ thấy thay đổi ngay nhé 😘Screenshot 2024-11-10 at 5.08.01 PM.png

Note cho bạn nào dùng Windows: khi up lên có thể sẽ bị lỗi MongoDB không thể mount volume vào môi trường gốc được. (có thể dẫn tới db bị restart liên tục), đây là 1 issue với MongoDB và Docker đã được giải thích ở đây. Giải pháp cũng khá đơn giản, ta tạo 1 Docker volume - volume riêng biệt được quản lý bởi Docker, volume mà ta dùng đường dẫn (như mình vẫn làm) là dạng local volume. Ta cập nhật lại docker-compose.yml một chút như sau:

version: "3.4"

services:
  ....
  
  db:
    image: mongo:4.4
    volumes:
      - mongodata:/data/db # ----->>> Ở đây
    restart: unless-stopped
 
volumes:
  mongodata: #  ---->> Ở đây

Khi up thì mongo có thể mất một chút thời gian để khởi động, nên nếu các bạn có login/register mà thấy bị treo, check log app thấy báo lỗi connect db thì chờ 1-2-3 phút rồi làm lại là được nhé (nhất là các bạn dùng Windows) 😊

Vọc vạch

Các bạn thử tạo cho mình 1 account rồi login vào tạo vài ba sản phẩm.

Sau đó các bạn thử shutdown project này đi sau đó khởi động lại bằng cách chạy command sau:

docker compose down
docker compose up -d

Sau đó thử login lại bằng tài khoản cũ và ta sẽ vẫn thấy data được giữ nguyên nhé.

Thử mở folder .docker/data/db, trong đó các bạn sẽ thấy rất nhiều file, đó là những thứ cần thiết để lưu lại data cho MongoDB, tương tự các bạn mở folder .docker/data/redis cũng thế nhé:

Screenshot 2024-11-10 at 5.07.15 PM.png

Screenshot 2024-11-10 at 5.07.19 PM.png

Tiếp theo ta lại thử shutdown project đi bằng command:

docker compose down

Sau đó ở file docker-compose.yml ta thử không mount dữ liệu của mongo vào và xem thế này nhé, ở service db các bạn sửa lại như sau:

db:
    image: mongo:4.4
    #volumes: # comment đoạn này lại
     # - .docker/data/db:/data/db
    restart: unless-stopped

Sau đó ta khởi động lại project bằng command:


docker compose up -d

Thử login lại thì sẽ không được nữa nhé, vì khi container được khởi tạo lại thì mọi thứ lại trống trơn, data của ta ko được mount nên cũng sẽ không còn nữa

Tương tự ở service app nếu ta không mount volume thì khi sửa code và F5 trìnhd duyệt sẽ không có gì thay đổi cả, hoặc khi bạn tạo sản phẩm upload ảnh check ở folder /public/images thì cũng không thấy ảnh đâu nữa cả

Deploy

Ở phần này chúng ta sẽ cùng nhau chạy project này như một project lúc chạy thật (production) xem sao nhé.

Vì có thể có nhiều bạn không có điều kiện để thuê một server (VPS) riêng, nên chúng ta sẽ làm "mô phỏng" bằng cách tạo một folder bất kì ở trên máy và thực hành nha

Build Image cho production

Giả sử các bạn thấy code của mình dev đã ngon, mọi thứ ổn và giờ chúng ta sẽ build image để chạy thật

Ở file Dockerfile các bạn sửa lại như sau:

FROM node:22-alpine

WORKDIR /app

COPY . .

RUN npm install

# Development
# CMD ["npm", "run", "dev"]

# Production
RUN npm install -g pm2
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]

Ở trên điều khác biệt duy nhất là ta dùng PM2 để chạy project: https://pm2.keymetrics.io/

PM2 (process manager) là một tool để ta chạy và quản lý ứng dụng NodeJS (có cả python nữa), dùng PM2 ta có thể thiết lập nhiều cấu hình chi tiết cho việc chạy project, đồng thời điều hay ho của PM2 là sẽ tự động restart project nếu như quá trình chạy có lỗi xảy ra, ví dụ như các lỗi mà ta không bắt Exception chẳng hạn

Ở trên ta dùng PM2 chạy project với những cấu hình ta đặt ở file ecosystem.config.js

Nhưng trước khi build ta sẽ tạo file .dockerignore để bỏ qua một số file/folder không cần thiết cho quá trình build nhé, các bạn tạo file .dockerignore với nội dung như sau:

# Bỏ qua node_modules vì lát nữa ở Dockerfile sẽ chạy npm install
node_modules

# Bỏ qua folder .docker vì folder này chỉ có service db và redis mới cần (ta đang build image cho service app)
.docker

# Bỏ qua ảnh mà chúng ta đã upload lên trong quá trình test
public/images/*

# Bỏ qua file .env, file này dùng cho docker-compose khi chạy nên không cần đưa vào image
.env

# Bỏ qua Dockerfile không đưa vào image vì file này chỉ dùng tại thời điểm build image
Dockerfile

# Bỏ qua file docker-compose vì file này chỉ dùng tại thời điểm khởi chạy project
docker-compose.yml

Sau đó ta build lại image bằng command:

docker build -t learning-docker/docker-node-mongo-redis:production .

Push image lên registry

Như ở bài dockerize ứng dụng Python mình đã hướng dẫn các bạn cách đẩy image lên registry (nơi lưu Docker image, giống như Github lưu code), và cùng với đó là cách pull về và chạy rồi nhé

Ở bài này ta lại làm tương tự, yêu cầu là các bạn đã có tài khoản Gitlab và có tạo sẵn 1 repository đặt tên là docker-node-mongo-redis nha:

Screenshot 2024-11-10 at 5.13.17 PM.png

Sau khi tạo Repo thì ta vào Container registry để xem tên image ta cần đặt là gì nhé:

Screenshot 2024-11-10 at 5.15.00 PM.png

Screenshot 2024-11-10 at 5.15.56 PM.png

Như ở trên các bạn thấy thì ta cần phải để tên image theo pattern: registry.gitlab.com/<username>/docker-node-mongo-redis (username các bạn thay vào cho đúng với của các bạn nha)

Để đẩy image lên registry thì việc đầu tiên ta cần làm là đổi lại tên image cho đúng với chuẩn của Gitlab. Các bạn chạy command sau:

docker tag learning-docker/docker-node-mongo-redis:production registry.gitlab.com/maitrungduc1410/docker-node-mongo-redis

thay tên Gitlab username của các bạn vào nha

Command hơi dài tí nhưng mình muốn làm rõ để các bạn được rõ 😁

Oke thì ta push image lên Gitlab nha:

docker push registry.gitlab.com/maitrungduc1410/docker-node-mongo-redis

thay tên Gitlab username của các bạn vào nha

Sau khi command chạy xong chúng ta lên Gitlab, chọn Repository và mở Deploy -> Container Registry ta sẽ thấy image của ta ở đó nhé:

Screenshot 2024-11-10 at 5.20.03 PM.png

Bắt đầu deploy

Như ở đầu mình đã nói là chúng ta sẽ "mô phỏng" deploy vì khả năng cao rất nhiều bạn không có điều kiện để có server thật để test, nhưng nếu các bạn có server (VPS) xịn thì cứ follow những bước mình hướng dẫn vẫn chạy bình thường nhé.

Chúng ta tạo riêng một folder tên test-deploy ở bất kì đâu các bạn muốn nha.

Ở trong folder đó ta tạo file docker-compose.yml với nội dung như sau:

services:
  app:
    image: registry.gitlab.com/maitrungduc1410/docker-node-mongo-redis
    volumes:
      - ./public/images:/app/public/images # ta chỉ cần mount mỗi folder image thôi nhé
    environment: # phần này ta định nghĩa ở file .env nhé
      - DB_HOST=${DB_HOST}
      - DB_NAME=${DB_NAME}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - PORT=${PORT}
    ports:
      - "${PORT}:${PORT}" # phần này ta định nghĩa ở file .env nhé
    restart: unless-stopped
    depends_on:
        - redis
        - db
  
  db:
    image: mongo:4.4
    volumes:
      - .docker/data/db:/data/db
    restart: unless-stopped
  
  redis:
    image: redis:5-alpine
    volumes:
      - .docker/data/redis:/data
    restart: unless-stopped

thay tên Gitlab username của các bạn vào nha

Sau đó ta tạo file .env với nội dung như sau:

PORT=3000
DB_HOST=db
DB_PORT=27017
DB_NAME=my_db
REDIS_HOST=redis
REDIS_PORT=6379

Và cuối cùng là chạy project thôi 💪, giờ phút của sự thật đến rồi, ta chạy command sau:

docker compose up -d

Khi chạy lên, docker-compose sẽ check những volume mà ta mount nếu ở bên ngoài chưa tạo folder thì docker-compose sẽ tự tạo cho ta nhé. Các bạn sẽ thấy như sau:

Screenshot 2024-11-10 at 5.30.54 PM.png

Và ta lại truy cập trình duyệt ở địa chỉ localhost:3000 (nếu bạn nào có server VPS riêng thì thay localhost bằng IP server của các bạn là được) và sẽ lại có được điều tương tự.

Vậy là ta đã hoàn thành việc deploy project như chạy thật rồi đó.

Điều hay ho của Docker

Như ở bài đầu tiên giới thiệu về Docker mình đã "quảng cáo" về độ tiện lợi của Docker khi ta chuyển môi trường, chuyển server.

Thì ở đây giả sử sau khi bạn đã deploy thành công project chạy thật ngon lành rồi, mà có lí do nào đó bạn cần phải chuyển sang server khác, Thì việc bạn cần làm là copy nguyên cái "đống" 😁 bên trên, tức folder test-deploy mà ta làm ở phần trên, và copy sang server mới, sau đó dùng 1 command:

docker compose up -d

Và Bùm 💥 mọi thứ lại chạy y như ở server cũ, không cần phải config gì thêm 😎 (nếu không có gì đặc biệt). Các bạn thử test bằng việc chạy ở một máy khác xem nhé 😉

Đây là 1 trong những điều tuyệt vời nhất mình yêu ở Docker ❤️❤️

Kết bài

Vậy là lại một bài nữa qua đi 💪

Hi vọng qua bài này các bạn đã hiểu được cách setup Docker cho project khi dev và khi deploy chạy thật sẽ như thế nào

Nếu có gì thắc mắc thì các bạn để lại comment bên dưới cho mình nhé

Toàn bộ source code cho bài này các bạn xem ở đây nhé (nhánh complete-tutorial nhé)

Cám ơn các bạn đã theo dõi và hẹn gặp lại các bạn ở những bài sau ^^


All rights reserved

Bình luận

Đăng nhập để bình luận
Avatar
@tomhagen
thg 12 23, 2019 6:36 SA

Cho mình hỏi nếu mình chỉ cần quan tâm đến Nodejs, React, Mongodb... thì có cần phải đọc mấy bài Dockerize Larevel, Python,... để nắm thêm khái niệm gì ko nhỉ, hay mỗi bài là 1 bài độc lập ? Thanks

Xem thêm (2)
Avatar

@hoc_anms e cũng có hỏi @maitrungduc1410 về vấn đề này, và ảnh cũng suggest là học từ đầu đến cuối series, e khuyên bác nên đọc hết vì còn nhiều thứ khá thú vị trong mỗi bài

Avatar
@hoc_anms
thg 2 4, 2021 12:02 CH

@duongrickysun thanks bạn nhiều nhé, mình đọc ko xót bài nào về chủ đề này của đại ca mình đâu b 😄

Avatar
@huynhnhutphi
thg 12 24, 2019 2:42 SA

Theo dõi từ bài đầu tiên của series, do lướt FB thấy. Bài viết rất hay, chi tiết và tốc độ publish bài mới chóng mặt =)), tưởng nhìn nhầm ngày T5-T6 (2 bài)-T7-CN

Cho mình hỏi thêm, mình có 1 project Laravel (gọi là app), và cấu hình webserver cho 2 sub-domain dùng chung 1 folder app, thì Docker có hướng giải quyết không bạn? VD:

  1. sys.exmaple.com => www/laravel-app
  2. api.example.com => www/laravel-app Hai domain điều cấu hình ở PORT 80, và còn queue jobs nữa Docker có thể giải quyết được ko? Thanks!
Avatar
@maitrungduc1410
thg 12 24, 2019 2:53 SA

tất cả đều được nhé bạn. Bạn có thể check qua website cá nhân của mình, tất cả 5 trang đó đều chạy trên Docker, 2/5 trang chạy bằng Laravel (có cả redis, queue, job, schedule task, laravel echo, socketio,...):

5 Trang trên mình có 1 bạn "Nginx" (đứng trước tất cả) làm nhiệm vụ là vừa là 1 webserver vừa là 1 reverse proxy điều hướng request vào trong các app chạy bằng Docker ở sau

Avatar
@huynhnhutphi
thg 12 24, 2019 3:02 SA

@maitrungduc1410 , cám ơn bạn 👍, mình sẽ tìm hiểu thêm. tài khoản mình mới nên ko like cho cmt được 😟

Avatar
@maitrungduc1410
thg 12 24, 2019 3:05 SA

oke bạn nhé 😉

Avatar
@hoc_anms
thg 12 24, 2019 2:50 SA

Em có một góp ý nho nhỏ là trong file bin/www nếu đại ca khai báo process.env.PORT thì trong nodejs nó không hiểu được mà cần install package dotenv và khai báo để tạo biến môi trường .env cho global, như thế cho dễ thay đổi port ak 😋 port.png

Xem thêm (5)
Avatar
@maitrungduc1410
thg 12 24, 2019 3:32 SA

E check lại trong bài ở file docker-compose trường environment của service app a đã thêm vào PORT=${PORT} nhé

Avatar
@hoc_anms
thg 12 24, 2019 3:45 SA

hehe success rồi anh ơi :V công nhận tiện quá cơ 😍

Avatar
@noob
thg 12 27, 2019 2:37 SA

Chẳng là mình muốn thực hành từ bài trc dùng volumn để mapping code ra ngoài. Cấu trúc thư mục của mình. Screenshot from 2019-12-27 09-32-26.png

Dockerfile và docker-compose Screenshot from 2019-12-27 09-34-07.png

Mình đã thêm trong file .dockerignore node_modules để k mapping thư mục này. Sau đó chạy docker build và compose up thì đang bị báo lỗi là k tìm đc thư việc vì thư viện chưa đc install. Cho mình xin cách clear nhất để người khác clone project mình về chạy 2 lệnh docker-compose build và up là chạy đc. Tks bạn

Xem thêm (4)
Avatar
@noob
thg 12 31, 2019 2:01 SA

src chỉ có source code thôi bạn, cùng cấp với node_modules còn nhiều file liên quan khác như package.json, public... mình vẫn đang tìm giải pháp cho vụ này.

Avatar
@maitrungduc1410
thg 12 31, 2019 2:26 SA

Theo mình dựa vào nhu cầu của bạn bạn chỉ cần map những thứ nào hay thay đổi nhiều nhất (source code, và public nơi chứa các file dạng image/ audio, thường xuyên sinh ra).

CÒn nếu bạn vẫn muốn map toàn bộ tất cả folder ngoài vào trong thì đương nhiên là bên ngoài sẽ luôn "ghi đè" và làm mất node_modules bên trong container vì bên ngoài ko có node_modules bạn à 😃

Avatar
@huy_nguyen
thg 12 28, 2019 6:22 SA

Dear Chung,

  • Cho mình hỏi khi mình lấy về làm step by step thì khi docker-compose up, cái app nó báo lỗi và exit luôn. Log báo là không tìm thấy nodemon 11.png
  • Có liên quan gì tới npm install trong Dockerfile không nhé. Vì khi chạy mình không thấy sinh ra node_modules.

Cảm ơn Chung

Avatar
@maitrungduc1410
thg 12 28, 2019 7:38 SA

Chào Huy,

Sorry bạn mình viết thiếu một bước, không biết sao lúc viết bài đầu óc mình lại thế nào 😄

Mình đã sửa lại trong bài mục Chạy Project, bạn có thể đọc lí do ở đó nhé

Cách fix nhanh cho bạn, bạn chạy command sau là được nhé:

docker run --rm -v $(pwd):/app -w /app node npm install

Sau đó khởi động lại project bằng cách chạy docker-compose down/up

Hi vọng giúp được bạn 😃

Avatar
@huy_nguyen
thg 12 28, 2019 9:05 SA

Dear Chung,

  • Đã thẩm thấu được vì sao mình copy node_modules vào thì chạy ok 😄. Cảm ơn bạn đã có những bài viết hữu ích cho những ai đang tìm hiểu Docker. Hy vọng bạn có nhiều bài viết hơn nữa đễ cho những người như mình LOVE docker nhiều nhiều hơn nữa bạn nhé.
  • Thật tuyệt với nếu bạn có một project Docker về HAProxy nhé 😄:D mình đang làm về nó mà chưa thông 💯💯💯💯💯💯
Avatar
@maitrungduc1410
thg 12 28, 2019 10:17 SA

Cám ơn bạn đã theo dõi blog của mình,

Mình sẽ cố gắng chia sẻ nhiều nhất có thể với các bạn nhé 😉

Avatar
@tienganh1247
thg 12 30, 2019 9:49 SA

Mình gặp lỗi "MongoNetworkError: failed to connect to server [db:27017]" mà chưa hiểu rõ nguyên nhân lắm, dùng luôn source của bạn để run, môi trường Windows.

Xem thêm (10)
Avatar
@tinpro123
thg 6 17, 2021 6:47 SA

@maitrungduc1410 em bị lỗi này ngồi fix 2 ngày không ra, sau đó thấy mấy anh tây hay để standalone volume cũng bắt chước làm theo và bùm, nó run, cái lỗi này rất take time cho anh em tìm kiếm. có 1 điều nữa là lúc khai báo services nên khai báo thêm container_name, container_name của db em khai báo là db luôn thì được, không cần dùng cái standalone volume.

Avatar

@tinpro123 tuyệt vời e , chạy đc là ngon.

  • còn về việc dùng container_name thì a ko khuyến khích, vì như thế container của e sẽ có tên "chính xác" thay vì để Docker tự generate thêm prefix để đảm bảo ko bị conflict với các project khác
  • thường a ít khi dùng standalone volume (tên chính xác phải gọi là Docker volume ấy, ko hiểu sao a lại nghĩ ra cái standalone 😄). dùng volume thường (volumn mount từ đường dẫn) thì mình dễ di chuyển qua lại, Docker volume thì nó do Docker quản lý.
  • với cả sao container_name lại liên quan tới volumn là thế nào hả e??!!!!
Avatar
@duc90
thg 1 3, 2020 4:20 SA

docker-compsoe.yml sai tên file này bạn ơi

Avatar

Cám ơn bạn nhiều nhé, mình đã sửa lại những chỗ viết sai, 1 sự sai lầm nhỏ nhưng hậu quả to 😄

Avatar
@nguyennhudat
thg 9 13, 2020 10:49 SA

B cho mình hỏi chút, mình muốn cấu hình với mysql, mình chạy kết nối với mysql, ko dùng docker chạy ok rồi. Nhưng chạy với docker đang báo lỗi ConnectionRefusedError [SequelizeConnectionRefusedError]: connect ECONNREFUSED 127.0.0.1:3306 . Trong code mình ko dùng .env mà dùng một file js config để lấy username, host, password... Có cần phải cấu hình để kết nối với mysql dùng .env ko b nhỉ? Mình cũng muốn hỏi thêm là làm sao mysql trong docker-compose khi pull về có thể kết nối với username, password... đã khai báo b nhỉ, mình đang hiểu là khi pull image mysql thì nó chưa có username nào? Cảm ơn b!

Xem thêm (3)
Avatar
@nguyennhudat
thg 9 13, 2020 1:43 CH

@maitrungduc1410 ok, cảm ơn b nhé 😀

Avatar
Avatar
@NanaCongchua
thg 9 21, 2020 9:48 SA

Thấy bài của trung là 1 vote + 1 cmt xong đọc bài. Rất tích cực trả lời cmt. Keep going bro!!!

Xem thêm (2)
Avatar
@maitrungduc1410
thg 9 21, 2020 10:37 SA

@NanaCongchua thời gian tới có thời gian mình sẽ quay lại viết tiếp series về Vue, vẫn còn nhiều điều ấp ủ nhưng chưa viết được 😂😂

Avatar
@NanaCongchua
thg 9 21, 2020 10:43 SA

@maitrungduc1410 I'm hungry for more 😄

Avatar
@myphuong
thg 9 22, 2020 4:26 SA

sao tui chạy docker run --rm -v /$(pwd):/app -w //app node:13-alpine npm install rồi mà khi run vẫn báo error 2020-09-22_112611.jpg

Xem thêm (6)
Avatar
@myphuong
thg 9 25, 2020 1:13 SA

@maitrungduc1410 ok bạn, đã chạy được 😃

Avatar

@myphuong tuyệt vời 💪💪

Avatar
@ducmaster
thg 10 10, 2020 4:26 CH

Volume riêng biệt được quản lý bởi Docker là nó lưu ở đâu trên máy vậy a. khi compose-down nó k bị mất data, vậy làm sao để xoá a

Avatar
@maitrungduc1410
thg 10 11, 2020 2:07 SA

Dạng volume đó gọi là Docker volume (Trong bài a gọi nó là standalone volume nghe có vẻ không đúng 😄), dạng volume này được quản lý bởi Docker ở /var/lib/docker/volumes/ (nếu máy gốc của e là Linux, trên Windows thì a search thấy đường dẫn nó dao động, mỗi người bảo 1 kiểu 😄).

Volume bình thường mình mount từ đường dẫn thì gọi là local volume. Cái này a thường dùng và e đọc các bài của a cũng thấy ta đều dùng nó cả. Vì dạng volume này do chúng ta quản lý nên sẽ dễ hơn.

Để xoá Docker volume thì đầu tiên e list ra danh sách Docker volume để tìm tên chính xác của nó (lí do là vì nếu e khai báo Docker volume ở trong docker-compose.yml thì nó sẽ được gắn thêm tiền tố nên ta phải check chính xác tên volume là gì trước khi xoá)

docker volume ls

Sau đó e muốn xoá volume nào thì e dùng command:

docker volume rm <tên volume>

Muốn xoá Docker volume thì dùng command như bên trên a bảo, tuyệt đối không tò mò vào hẳn folder /var/lib/docker/volumes/ xoá bằng tay nhé e, nát Docker đấy 😂😂

Avatar
@nambui2000k
thg 11 7, 2020 9:40 SA

Chào anh, anh cho e hỏi để có thể truy cập dữ liệu ở .docker/data/db bằng MongodbCompass thì truy cập như thế nào ạ? Em cảm ơn ạ!

Avatar
@maitrungduc1410
thg 11 7, 2020 10:05 SA

để truy cập data của Mongo bằng 1 tool quản trị CSDL (MongoDB compass, Studio 3T,....) thì e cần phải map port của container db để nó có thể được truy cập từ máy của e.

#docker-compose.yml

...
db:
  ports:
    - "8000:27017" # chọn cổng 8000 hoặc cổng nào tuỳ e thích

Sau đó ở MongoDB Compass e connect tới cổng 8000 là đc nhé

Avatar
@nambui2000k
thg 11 8, 2020 5:00 SA
Avatar
@nambui2000k
thg 11 8, 2020 5:01 SA
Avatar
@nambui2000k
thg 11 8, 2020 5:02 SA

Chào a, e chạy lần đầu đăng ký tài khoản, đăng nhập , thêm sản phẩm bình thường. Xong e docker-compose down --> docker-compose up để restart lại docker thì bị lỗi " Failed to connect to mongo on startup - retrying in 5 sec MongoNetworkError: failed to connect to server [db:27017] on first connect [Error: getaddrinfo ENOTFOUND db app_1 | 2020-11-08T04:54:54: at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26) { app_1 | 2020-11-08T04:54:54: name: 'MongoNetworkError' app_1 | 2020-11-08T04:54:54: }]"

Em docker ps thì 2 cái image kia đã chạy. Còn mongo thì Restaring suốt. Có cách khắc phục k ạ? Em cảm ơn.Capture.PNG

Xem thêm (8)
Avatar
@nambui2000k
thg 11 8, 2020 8:47 SA

@maitrungduc1410 ok a. E cảm ơn a ạ. Các bài viết của a hay và dễ hiểu quá.

Avatar

@nambui2000k

oke e nhé 💪💪💪

Avatar
@nambui2000k
thg 11 9, 2020 10:43 SA

A cho em hỏi. Sao e chạy trên centos7 thì n không nhận file .env ạ?Capture.PNG

Xem thêm (4)
Avatar
@maitrungduc1410
thg 11 10, 2020 7:18 SA

@nambui2000k ủa trước giờ e vẫn quen làm như vậy à 😃, a xem ảnh của e cũng ko để ý cái đó thật 😄

Từ giờ nhớ cho chỗ này và cả các project khác nhé e, đừng để space vào, luôn viết liền SOME_VAR=123 nhé 😎😎

Avatar
@nambui2000k
thg 11 10, 2020 7:20 SA

@maitrungduc1410 ok . e cảm ơn a nha

Avatar
@nambui2000k
thg 11 11, 2020 1:46 SA

a cho e hỏi: Ví dụ app nodejs port 3000 E dùng container nginx để proxy_pass sang port 3000 của app với e map thẳng port "80:3000" ở container app thì có khác thì có khác gì nhau không ạ? Em cảm ơn ạ.

Xem thêm (2)
Avatar
@maitrungduc1410
thg 11 11, 2020 2:46 SA

@nambui2000k ,

về cơ bản dùng 1 webserver để serve request từ user (proxy, cache, load balance,....) sẽ tốt hơn, đặc biệt nginx làm rất tốt điều đó. Do vậy e nên có 1 con nginx đứng trước để proxy request là tốt nhất, nó ko chỉ đơn thuần để proxy mà e có thể có nhiều config để xử lý request từ user hoặc response từ phía backend của e (load balance, redirect, rewrite, deny, add header,...)

Thế nhưng việc thêm vào 1 container proxy này cũng có khi gây ra nhiều vấn đề nếu e ko quen vận hành nó, trong trường hợp đó thì e cứ dùng luôn service app là cũng đủ rồi từ từ học dần thêm 😃

Avatar
@nambui2000k
thg 11 11, 2020 2:47 SA

@maitrungduc1410 ok a. E cảm ơn a ạ.

Avatar
@cristiano
thg 5 14, 2021 10:24 SA

Anh ơi, em cứ lỗi err.png thì anh có thể chỉ em cách fix được ko em dùng wsl ubuntu 18.04 ạ! err.png

Xem thêm (2)
Avatar

@cristiano khả năng cao là lúc mount volume có lỗi j đó, kiểu bên windows có lỗi khi dùng local volume với MongoDB á, dùng Docker volume (như e đang làm) thì sẽ fix đc.

Avatar

@cristiano Server báo lỗi error là gì e? Logs của phía nodejs báo thế nào, e chạy docker-compose logs app xem nhé

Avatar
@sangmeo
thg 8 12, 2021 9:27 CH

cho em hỏi là có cần thêm network trong docker-compose vào không ạ để connect các container lại với nhau ạ

Xem thêm (2)
Avatar
@sangmeo
thg 8 14, 2021 2:04 SA

@maitrungduc1410 Kakaka em cũng đọc xong hết series này rồi anh, rất dễ hiểu, mong anh làm thêm về series kubernes để connect với những phần ở đây thì tuyệt

Avatar

@sangmeo nhiều bạn cũng comment hỏi a về series kubernetes, a cũng đau đáu lắm mà chưa có tgian 😅😅

Avatar

Mình cài trên Windows 10 và có vấn đề trong việc cài đặt node_modules Câu lệnh như trong hướng dẫn docker run --rm -v "/$(pwd)":/app -w //app node:13-alpine npm install báo lỗi, không thực hiện được trên windows 10 (máy mình). Ban đầu mình cài Node lên windows, nhưng thấy có vẻ không ổn, vì như vậy 2 phiên bản có thể khác nhau

Mình đã thực hiện theo hướng dẫn tại https://stackoverflow.com/questions/51097652/install-node-modules-inside-docker-container-and-synchronize-them-with-host

Nội dung các file thay đổi như sau

Dockfile

FROM node:13-alpine
WORKDIR /app

COPY . .

# Tạo thư mục cache 
RUN mkdir /cache
WORKDIR /cache

# cài đặt vào the node_modules's cache directory.
COPY package.json ./
#COPY package-lock.json ./
RUN npm install

# Chuyển về làm việc tại thư mục /app 
WORKDIR /app

# Development
CMD ["npm", "run", "dev"]

# Production
# RUN npm install -g pm2
# CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]

Tập tin docker-compose.yml

version: "3.4"

services:

  app:
    image: learning-docker/docker-node-mongo-redis:v1
    volumes:
      - ./:/app # mount từ môi trường gốc vào trong để nếu các bạn thay đổi code thì bên trong sẽ tự động cập nhật
    
    environment: # phần này ta định nghĩa ở file .env nhé
      - DB_HOST=${DB_HOST}
      - DB_NAME=${DB_NAME}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - PORT=${PORT}
    ports:
      - "${PORT}:${PORT}" # phần này ta định nghĩa ở file .env nhé
    command: /app/entrypoint.sh # Có thêm dòng này 
    restart: unless-stopped
    depends_on:
        - redis
        - db
  
  db:
    image: mongo
    volumes:
      - .docker/data/db:/data/db
    restart: unless-stopped
  
  redis:
    image: redis:5-alpine
    volumes:
      - .docker/data/redis:/data
    restart: unless-stopped

Cuối cùng là thêm file entrypoint.sh

#!/bin/bash

cp -r /cache/node_modules/. /app/node_modules/
exec npm start

Sau khi cài đặt xong, đã truy cập được trang web như hình

2021-09-26 12_15_07-Login.png

Avatar

tuyệt vời bạn ơi, cám ơn bạn đã tìm ra vấn đề và giải pháp cho việc này, mong là giúp được các bạn đọc sau

Avatar
@hieplevuc
thg 5 3, 2022 3:03 SA

Chào bạn mình làm theo cách của bạn ở trên Win11 nhưng khi chạy docker-compose up thì nó báo lỗi /usr/local/bin/docker-entrypoint.sh: exec: line 11: /app/entrypoint.sh: not found Không biết bạn đã từng gặp vấn đề này chưa ? bạn có thể cho mình xin cách giải quyết được không ?

Avatar
@thangnk
thg 11 12, 2021 2:28 CH

Em chào a, em đang ngâm cứu serial học docker của a. Mong a có thời gian thông não giúp em bài toán này với ạ
Hiện tại em đang muốn implement 1 model S2T sử dụng flask + docker thành 1 web api
Em đang dự định thiết kế các service như sau: nginx, app(chứa flask), db(chứa mysql hoặc mongo)
Nhưng em có 1 vấn đề ở đây là e có dùng tensorflow (và 1 số thư viện khác), thì em có cần thiết tạo 1 service mới (service S2T chẳng hạn) để đảm nhiệm việc xử lý và train model ko ạ ? Khi đó cách kết nối service app với service S2T là ntn ạ

Xem thêm (2)
Avatar
@thangnk
thg 11 13, 2021 12:03 CH

@maitrungduc1410 A cho em hỏi thêm chút ạ
Src code của e được để chung ở 1 chỗ duy nhất ấy ạ
Khi các service được định nghĩa như trên, service app của em chỉ chứa flask (không có các method của tensorflow kiểu như load_weight hay predict) thì em làm sao có thể sử dụng được ạ ?
Kiểu em chưa hiểu rõ là src code viết chung nhưng môi trường lại chia rẽ ra thì làm tn để chạy được ấy ạ
Mong a giải đáp giúp em ạ

Avatar
@maitrungduc1410
thg 11 14, 2021 2:38 SA

@thangnk e viết cho chúng mỗi cái 1 dockerfile riêng thì mỗi cái sẽ có 1 môi trường riêng, trong dockerfile thì e chỉ copy các file cần thiết cho service e cần thôi nhé

Avatar
@thanhnx9368
thg 11 18, 2021 1:08 CH

Chào bạn, cho mình hỏi chút. Mình push image production lên docker hub, sau đó tạo 1 folder để test deploy. Sau đó chạy docker-compose up thì cứ bị lỗi này.

Trong khi đó ở image app, mình dùng image của bạn lại ko bị lỗi. Bạn có thể cho mình biết mình thiếu ở bước nào không nhỉ?

Đây là repo docker hub của mình: https://hub.docker.com/repository/docker/thanhnx9368/docker-node-mongodb-redis

Screen Shot 2021-11-18 at 8.05.35 PM.png

Xem thêm (5)
Avatar
@thanhnx9368
thg 11 19, 2021 4:31 CH

@maitrungduc1410 À thì ra lifecycle của nó:

  • Lần đầu Máy host mount > container.
  • Sau đó 2 thằng sẽ sync với nhau.
  • Nếu container có data thì sẽ sync ngược lại máy host... và tương tự ngược lại. Phần này nếu ko nắm vững lifecycle của nó cũng mệt phết 😅

Cảm ơn bạn nhé, giải thích chi tiết và dễ hiểu quá. 😊

Avatar
@maitrungduc1410
thg 11 20, 2021 2:09 SA

@thanhnx9368 okie bạn nhé 😁

Avatar
@tmphuong
thg 1 6, 2022 10:02 SA
Avatar
@tmphuong
thg 1 6, 2022 10:04 SA
Avatar
@tmphuong
thg 1 6, 2022 10:07 SA
Avatar
@tmphuong
thg 1 6, 2022 10:23 SA
Avatar
@naamle
thg 4 7, 2022 2:38 CH

Cảm ơn tuto rất hay của bạn về docker và các project thực hiện với docker. Trong bài này, mình có access (root) đến server, nhưng chỉ là shell, ko phải graphic access. Mình cấu hình mãi ko được cái ssh tunneling để có thể truy cập đến page được served bởi container app. Bình thường vụ port forwarding này rất đơn giản: VD mình chạy jupyter notebook trên server, port 8888 trên host chẳng hạn, sau đó fwd đến localhost:8000 là có thể dùng browser thao tác với các notebook trên server.

Trường hợp này bạn có thể thêm phần hướng dẫn đó được ko?

Avatar

khi bị lỗi ko access được vào app của bạn thì bạn cứ debug từng bước 1 nhé:

  • bạn đã map port app của bạn chưa (ví dụ: map ra host là port 8000)
  • Nếu đã map, vậy bạn ssh vào server chạy curl localhost:8000 có nhận đc response hay ko?
  • Tiếp sau đó là thử truy cập từ bên ngoài internet dùng IP server curl ip_server:8000 -> nếu bước này ko được thì có 2 khả năng: 1 là bạn chưa mở cho traffic đi vào từ internet qua cổng 8000 (thường cấu hình trên cloud provider). Hoặc trường hợp 2 là app của bạn ko cho phép traffic bên ngoài gọi tới, mà chỉ cho phép gọi localhost (tức là gọi cùng server), khá giống với Python Flask, mặc định chỉ cho phép gọi từ localhost, xem thêm ở đây nhé

Tổng kết lại, mình ko nghĩ là việc ko gọi được vào app của bạn nó lại liên quan tới việc access từ account của bạn vào server

Avatar
@sangndt94
thg 9 14, 2022 3:27 CH

Bài hay lắm nha chủ thớt, mình góp ý xíu chỗ docker tag thiếu docker push á bác

Avatar

cám ơn bạn đã góp ý ❤️

Avatar
@nguyentrongvy
thg 10 9, 2022 4:41 SA

sao mình thay đổi code mà trong container vẫn k tự động thay đổi bạn ơi

Avatar

bạn kiểm tra lại docker-compose.yml xem đã mount code từ ngoài vào trong chưa?

volumes:
      - ./:/app

Quan trọng hơn chú ý trong bài mình dùng command "npm start" để chạy project, và mặc định nó không "watch" khi code thay đổi:

Screenshot 2022-10-09 at 11.45.05 PM.png

Bạn đổi thành như sau và build lại image nhé:

args: "run dev"
watch: true
Avatar
@thangthien
thg 12 16, 2022 3:42 SA

@maitrungduc1410 Anh cho em hỏi bài trước khi Dockerize Laravel em thấy có dùng nginx sao bên này lại không dùng vậy ạ.

Avatar
@maitrungduc1410
thg 12 17, 2022 4:08 SA

vì app PHP thì nó cần có 1 webserver để nhận request từ bên ngoài sau đó pass vào php-fpm.

còn ở bài này thì mình dùng nodejs bản thân nó đã là 1 webserver sẵn rồi. Nếu e thích e có thể đặt 1 con nginx phía trước nodejs giống bài Laravel cũng đc, nhưng ko cần thiết 😃

Avatar
@Javis00
thg 12 22, 2022 10:40 SA

a cho e hỏi là đến bước test-deploy rồi, đã tạo docker-compose.yml và .env file. nhưng khi compose up thì nó lại báo là node_module missing. Vậy khi deploy thì server có cần chạy 1 Node container để install node_modules trước khi compose up không ?

Avatar
@maitrungduc1410
thg 12 23, 2022 2:59 CH

thực tế, cách a hay làm nhé: đó là không dùng container node tạm thời để install node_modules, mà viết trực tiếp vào Dockerfile (npm install).

Như vậy thì khi nhìn vào Dockerfile ta có được cái nhìn tổng quát, tất cả mọi thứ cần để build image, deploy và chạy được

Avatar
@tict
thg 2 16, 2023 6:36 SA

Hi bạn,

Bài viết rất hay và đầy đủ, mình có làm theo hướng dẫn thì ở khúc deploy thì thay vì phải tạo một folder trên máy local thì mình thuê hẳn một con server để test, mọi chuyện đang rất ổn cho đến khi mình bắt đầu chạy câu docker-compose up thì nó báo lỗi ở trong container app: exec /usr/local/bin/docker-entrypoint.sh: exec format error

Mình đã thử nhiều cách như là thêm quyền exec cho file cũng như là thử restart nhưng đều không được, hiện tại trên máy mình vẫn hoạt động bình thường chỉ có trên server thật thì mới ko chạy được thôi.

Hy vọng bạn có thể giúp mình,

Thanks.

Một vài thông tin thêm:

  • docker-compose của mình trên server

image.png

  • .env của mình trên server:

image.png

  • Dockerfile của mình dưới local:

image.png

Avatar

là sao bạn nhỉ?

vậy là bạn bị lỗi khi docker compose up ... hay là lỗi khi exec vào container docker compose exec app sh ?

Avatar
@tict
thg 2 17, 2023 9:26 SA

lỗi là khi mình chạy docker compose up ... nha, do mình không có lệnh -d nên nó hiện thị log bên trong container app luôn

Avatar

@tict khả năng là do image được build với architecture khác với trên server của bạn rồi, lỗi này giống như hội dùng MacBook M1: https://stackoverflow.com/questions/73285601/docker-exec-usr-bin-sh-exec-format-error

docker-compose.yml, service app, bạn set platform: linux/amd64 xem nhé

Avatar
@WRBKOR23
thg 3 20, 2023 3:40 CH

Cho e hỏi là tên của service mình khai báo trong file docker-compose thì đặt là gì cũng được phải ko ạ? E muốn đổi tên service db thành mongo thì phải sửa ở đâu nữa ko a, vì e run thì lỗi kết nối với db. E kp dev node nên ko rõ lắm.

Xem thêm (4)
Avatar
@WRBKOR23
thg 3 24, 2023 3:09 CH

@maitrungduc1410 cho e hỏi là cái db_name thì sao mà mongo nó hiểu để tạo ra ạ. Và nếu mình muốn đổi port của mongo và redis thì phải làm sao ạ? Em cảm ơn

Avatar

@WRBKOR23 mongo + redis thì bên trong container nó đã luôn chạy port 27017 và 6379 rồi, e ko đổi được (Trừ khi e tự build lại image của nó, mà chả ai rảnh mà làm vậy 😃)

ở đây e chỉ có thể đổi port mà e map ra môi trường ngoài thôi, ví dụ:

db:
    image: mongo:4.4
    ports:
      - "8888:27017"

Còn về việc DB_NAME, thì Mongo khác với các loại SQL DB đó là ta ko cần tạo trước db (collection), mà khi ta insert vào mongo sẽ check nếu collection (db) chưa được tạo thì nó sẽ tạo cho.

Nếu e muốn tạo sẵn collection ngay lúc chạy container mongo thì e truyền thêm biến môi trường MONGO_INITDB_DATABASE là được. Xem thêm ở đây nhé: https://hub.docker.com/_/mongo

Avatar
@duyanh4788
thg 4 17, 2023 10:26 SA

chào bạn mình đang bị lỗi connect ECONNREFUSED 127.0.0.1:6379 redis , nhờ bạn xem và giúp mình với :

image.png image.png

Avatar

bạn đang ở trong service app thì làm sao bạn lại connect tới redis ở 127.0.0.1 được 😃

mà nó phải là redis:6379 nhé. "redis" là tên của service redis, dòng số 42 như trong file docker-compose.yml của bạn.

Bạn cần phải sửa lại REDIS_URL

Avatar
@duyanh4788
thg 4 18, 2023 4:18 CH

@maitrungduc1410 tks bạn hôm qua mình search và fix đc rồi , mongo cũng tương tự

Avatar

@duyanh4788 oke bạn nhé

Avatar
@Croud141
thg 7 5, 2023 4:39 CH

Hello anh, em xin phép hỏi một câu ạ 😅.
Em thấy trong file .dockerignore của anh có ingnore node_modules và anh có chú thích rằng là do mình có chạy npm install trong Dockerfile Em thấy nó đang hơi mâu thuẫn với việc mình phải tạo container tạm thời để chạy npm install khi dev ạ. Anh có thể giải thích cho em rõ hơn chút được k ạ.
Em đang nghĩ là có thể do npm install -g chăng 🤔
Em cảm ơn ạ.

Avatar

có vẻ là e đang bị hiểu lầm các trường hợp đó với nhau 😄

  • việc thêm node_modules vào dockerignore là để đảm bảo, chẳng may trong trường hợp môi trường ngoài của e có node_modules thì mình ko copy nó vào lúc build image, bởi vì node_modules có thể bị ảnh hưởng bởi môi trường, nên ở môi trường nào thì ta nên chạy lại npm install cho môi trường đó và k dùng lại node_modules của môi trường khác
  • ý thứ 2 là dùng container tạm thời để dev: là mục đích trong trường hợp môi trường gốc của mình ko có nodejs luôn (ko có npm), mình ko muốn cài nodejs mà vẫn muốn dev, thì mình tận dụng container thời, tạo container node để chạy npm install, cái node_modules đc sinh ra là từ container mà ra, sẽ tương thích, phù hợp để dev trực tiếp trong container
Avatar
@Croud141
thg 7 7, 2023 5:02 SA

@maitrungduc1410 Câu trả lời rất ngắn gọn xúc tích và dễ hiểu ạ. Cảm ơn a 🤟

Avatar

@Croud141 oke e nhe

Avatar
@huynhttdev
thg 11 22, 2023 7:49 SA

A ngâm cứu làm thêm series về Redis đi a, e thấy phần này cũng khá nhiều vấn đề để nói đó ạ

Avatar
@maitrungduc1410
thg 11 22, 2023 2:38 CH

oke e nhé, 😃

Avatar
@nguyenhuuduc458
thg 12 19, 2023 7:56 SA

Series hay lắm, hóng một bài dockerize về springboot của bạn

Avatar
@datnx
thg 1 11, 2024 4:52 CH

4.PNGHello anh, em có làm được hết bài hướng dẫn này nhưng em có 1 câu hỏi phần cuối. Lúc em deploy trên test-deploy (em có compose down cái kia rồi) thì khi em login vào nó lại báo "Email or password is incorrect". Nhưng khi em quay trở lại deploy project chính thì lại login vào bình thường. Có vẻ database trong 3.PNGtest-deploy của em chưa được lưu sang. Không biết cách giải quyết vấn đề này là gì ạ ? 1.PNG2.PNG

Xem thêm (8)
Avatar
@datnx
thg 1 17, 2024 3:05 SA

@maitrungduc1410 Dạ vâng e thấy lỗi register 500 r ạ, nhưng nó k hiện error detail ạ

Avatar

@datnx ở 2 chỗ sau e log lỗi ra xem nhé:

  1. controllers/UserController.js

Thêm vào bên trên dòng này:

console.log(error)
  1. app.js Thêm vào bên trên dòng này:
console.log(err)

Sau đó build lại project và test lại sẽ thấy detail lỗi nhé

Avatar
@datnx
thg 1 16, 2024 10:09 SA
Avatar
@datnx
thg 1 16, 2024 4:16 CH
Avatar
@neko
thg 2 3, 2024 3:44 CH

e k bik e có sai gì không nhưng khi nhấn thêm sản phẩm nó xoay vòng :>

học mới 6 bài mà não xoay mù vì cố nén hết kiến thức vô đầu xong cái nhớ cái quên 😅nên chắc 1 project phải triển khai thực tế hơn chục lần mới ok a nhỉ :.>

Xem thêm (2)
Avatar
@neko
thg 2 4, 2024 1:31 CH

@maitrungduc1410 à ok r a chỗ số lượng sản phẩm e nhập chữ thay vì số 🤣

cảm ơn a

Avatar

@neko nhớ lần sau gặp lỗi thì phải check logs đầu tiên e nhé 😃

Avatar
@cogVien
thg 2 7, 2024 1:29 CH

chào anh trong bài này thì em chỉ thấy chỉ thay đổi được giao diện, còn phải xử lí bên trong thì không thay đổi, em đã thay đổi bên trong UserController ở phần register ở line 49 thay vì 'Server error' như anh đã code thì em thay bằng mess mới nhưng thấy nó thay đổi, em phải down và up lần nữa mới thay đổi ạ

Avatar

ý e là sao nhỉ?

e sửa code thì build lại project nhé, ở docker-compose.yml để ý dùng đúng tên image + tag e vừa build

Avatar
@Koruvika
thg 2 16, 2024 10:27 SA

Sau khi cài xong

docker run --rm -v $(pwd):/app -w /app node:16-alpine npm install

Em chạy với lệnh docker compose up thì gặp lỗi này, liên tục exit with code 0 và exit with code 14, lặp lại liên tục, em thử exec app cũng không được vì nó báo lỗi container is restarting. Mặc dù em đã check thấy có thư mục node_modules bên ngoài máy rồi. image.png

Xem thêm (6)
Avatar
@Koruvika
thg 2 18, 2024 1:57 SA

@maitrungduc1410 Em đã fix được rồi, ban đầu em để docker folder ở /mnt/data1/, sau khi em chuyển về folder /home/duong/ thì ko gặp lỗi gì, em nghĩ có thể do permission gì đó nên folder được mount không chạy services mongodb được 😢 image.png

Avatar

@Koruvika theo a nhớ /mnt thường mặc định là của root

nhưng fix đc là may rồi e ❤️

Avatar
@teracom22
thg 2 27, 2024 10:27 SA

👍️

Avatar
@neko
thg 3 25, 2024 10:57 SA
Avatar
@neko
thg 3 25, 2024 2:59 CH

image.png image.png

a cho e hỏi là :

1/ trong file docker-compose.yml REDIS_PORT=${REDIS_PORT}

tên bên trái với bên phải mình để sao cũng được miễn là nó giống với file .env đúng không ạ và chỉ cần để port trong biến môi trường vậy là nó tự động kết nối đến service khác như mongo redis bên ngoài hay sao a

3/ tại sao trong file .env có DB_PORT mà trong file docker-compose.yml lại không ghi DB_PORT vô phần environment mà e chạy dự án vẫn được vậy ạ

3.1/cái biến
DB_HOST=${DB_HOST}

để giúp kết nối đến service mongo mà không cần

port trong file.yml mà
REDIS_HOST=${REDIS_HOST} lại phải cần để port trong yml vậy ạ

Avatar
  1. DB_HOST=${DB_HOST}, cái bên trái là cái app bên trong container cần, phải chính xác, vế bên phải thì như nào cũng được miễn là khớp với .env

  2. app nó kết nối tới DB để lưu data, kết nối tới redis để lưu session đăng nhập

  3. DB_PORT nếu ko có thì nó lấy mặc định 27017, e check ở code nhé

Avatar
@neko
thg 3 25, 2024 3:38 CH

@maitrungduc1410 trời cảm ơn a trả lời sớm dữ , e đang ngồi ngẫm sửa lại cmt cho ra câu hỏi chỉnh chu thì a rep lun r :>

Avatar

@neko okie e 🤣🤣🤣

Avatar
+112
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí