+44

Dockerize project demo microservices của Google

Hello các bạn lại là mình đây 👋👋

Lâu rồi chưa được viết bài thêm nay lại thấy ngứa tay rồi, không biết dạo này công việc của các bạn như thế nào rồi nhỉ? 😚

Hôm nay ta lại tiếp tục với series Docker với một bài deploy full project e-commerce theo kiến trúc microservice, lấy từ demo của Google nhé. 🚀🚀

Câu chuyện là...

Câu chuyện là mình có được một người em chỉ cho xem repo này: https://github.com/GoogleCloudPlatform/microservices-demo

Ở đó ta có demo về một project e-commerce tới từ Google, với đầy đủ các service, mỗi service lại code bằng ngôn ngữ khác nhau, chạy độc lập, mình có xem tất cả những gì có trong repo đó và thấy là họ làm rất chỉn chu cho mục đích demo để ta có thể hiểu được một kiến trúc microservices khi deploy thật trông nó sẽ như thế nào.

Screenshot 2024-07-06 at 11.02.27 AM.jpg

Nhận thấy đây là một mảnh ghép còn thiếu cho series của mình, vậy là lại có ý tưởng viết bài mới liền 😝

Những thứ ta sẽ làm

Ở bài ngày hôm nay ta sẽ clone project của Google về: https://github.com/GoogleCloudPlatform/microservices-demo

Sau đó sẽ build từng service và cuối cùng là chạy project lên xem tổng thể như thế nào nhé. Thực tế bài này sẽ không dài, vì project của họ đã cho ta tất cả các file Dockerfile sẵn luôn rồi 😂

Mục đích của mình ở bài này như sau:

  • showcase dockerize/deploy microservices với Docker như thật sẽ thế nào
  • Flow build và run các services để giảm thiểu lỗi
  • xử lý các vấn đề liên quan trong quá trình build

Tổng quan

Ở đây ta có sơ đồ kiến trúc như sau: (cái này người ta đã cho sẵn ở repo của họ luôn)

architecture-diagram.png

Ở trên ta có tất thảy 11 services chính, cộng cả redis thì là 12, service nào call vào đâu đều được thể hiện rõ trên diagram

Thường khi ta làm thực tế, thì việc vẽ ra được sơ đồ như này rất quan trọng, lí do là để ta có thể hiểu được sự phụ thuộc của các service với nhau, phân chia network/VPC như nào cho phù hợp, hiểu được request flow thì khi gặp lỗi sẽ dễ hơn khi debug

Không vẽ ra được thì ta cũng phải đảm bảo là viết doc cho nó ở đâu đó nha 😎

Dựa vào diagram ta có, lát nữa ta sẽ dockerize làm 2 lần:

  • lần 1: các service không cần gọi vào service khác. Ví dụ: ad, productcatalog, cart (cái này gọi vào redis nhưng về mặt business ta cũng coi như nó không gọi vào serviec khác),...
  • lần 2: các service phụ thuộc vào service khác, ví dụ: frontend, checkout, loadgenerator,...

Bên dưới ta có chi tiết từng service như sau:

Service Ngôn ngữ Mô tả
frontend Go Là 1 HTTP server. Không yêu cầu đăng ký/đăng nhập và tự động tạo session ID cho tất cả người dùng.
cartservice C# Lưu trữ các sản phẩm trong giỏ hàng của người dùng trên Redis và truy xuất sau này.
productcatalogservice Go Cung cấp danh sách sản phẩm từ file JSON, cho phép tìm kiếm và lấy thông tin chi tiết từng sản phẩm.
currencyservice Node.js Chuyển đổi số tiền giữa các loại tiền tệ. Sử dụng tỷ giá thực tế lấy từ Ngân hàng Trung ương Châu Âu (ECB). Đây là dịch vụ có QPS (Query per second) cao nhất.
paymentservice Node.js Thanh toán với thông tin thẻ tín dụng giả (mock) và số tiền nhất định, trả về ID giao dịch.
shippingservice Go Dự toán chi phí vận chuyển dựa trên giỏ hàng. Gửi hàng đến địa chỉ được cung cấp (mock).
emailservice Python Gửi email xác nhận đơn hàng cho người dùng (mock).
checkoutservice Go Lấy giỏ hàng người dùng, chuẩn bị đơn hàng, điều phối thanh toán, vận chuyển và thông báo qua email.
recommendationservice Python Đề xuất các sản phẩm khác dựa trên các mặt hàng trong giỏ hàng.
adservice Java Cung cấp quảng cáo văn bản dựa trên các từ ngữ ngữ cảnh được cung cấp.
loadgenerator Python/Locust Liên tục gửi các yêu cầu mô phỏng hành vi mua sắm thực tế của người dùng đến frontend.

Ta bắt đầu nhé 🚀🚀

Setup

Bài này ta sẽ làm ở local với Docker, nên yêu cầu là máy các bạn đã cài Docker nha

Tiếp theo ta clone project từ repo của Google Cloud về nhé: https://github.com/GoogleCloudPlatform/microservices-demo

git clone https://github.com/GoogleCloudPlatform/microservices-demo.git

Sau khi clone về ta có project như sau:

Screenshot 2024-07-06 at 11.34.53 AM.png

Ở đây ta thấy họ đã chuẩn bị sẵn cấu hình cho nhiều các deploy khác nhau: Kubernetes với manifest hoặc kustomize, Helm chart, terraform,...

Bài này ta làm ở local nên ta sẽ build trực tiếp từ src, ở trong đó thì họ đã tổ chức các service theo từng folder rõ ràng cho ta:

Screenshot 2024-07-06 at 11.36.42 AM.png

Ta bỏ qua service shoppingassistantservice, hiện tại (07/2024) họ chưa có doc cho việc sử dụng service này như nào

Và ở trong mỗi service họ đã có luôn cả Dockerfile cho ta luôn:

Screenshot 2024-07-06 at 11.38.04 AM.png

Quá toẹt vời, chứ ngồi mà đọc project xong tự viết Dockerfile cho hơn chục services chắc chớt 😜😜

Dockerize lần một

Ở lần đầu ta sẽ dockerize tất cả các service mà không cần gọi tới service khác, bao gồm 7 service: ad, productcatalog, cart, shipping, currency, payment, email

Ta bắt đầu với adservice trước nhé, ta mở terminal ở folder src/adservice:

docker build -t adservice .

Chờ một tí thấy như sau là oke rồi:

Screenshot 2024-07-06 at 11.54.06 AM.png

Tiếp theo tới productcatalogservice, tương tự vẫn mở terminal ở folder src/productcatalogservice và chạy:

docker build -t productcatalogservice .

Tiếp theo tới cartservice, vì Dockerfile của service này nằm trong 1 folder src nữa:

Screenshot 2024-07-06 at 11.55.38 AM.png

Nên ta phải mở terminal ở đúng folder nhé src/cartservice/src:

docker build -t cartservice .

Tiếp theo tới các service còn lại, cái này mình làm nhanh, các bạn nhớ phải mở terminal ở đúng folder rồi mới chạy build nhé:

# src/shippingservice
docker build -t shippingservice .

# src/currencyservice
docker build -t currencyservice .

# src/paymentservice
docker build -t paymentservice .

# src/emailservice
docker build -t emailservice .

Vì tất cả các service đã được người ta viết sẵn Dockerfile hết rồi nên ta chỉ việc build lại thôi 😁

Sau khi build xong tất cả thì ta chạy lên xem có lỗi lầm gì không nhé.

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

services:
  adservice:
    image: adservice

  productcatalogservice:
    image: productcatalogservice
  
  cartservice:
    image: cartservice
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart
  
  redis-cart:
    image: redis:6-alpine

  shippingservice:
    image: shippingservice

  currencyservice:
    image: currencyservice

  paymentservice:
    image: paymentservice

  emailservice:
    image: emailservice

Ở trên ta sẽ chạy tất cả các service mà ta vừa build lên, bao gồm cả redis, chú ý rằng dựa vào diagram:

architecture-diagram.png

Ta thấy rằng cuối cùng chỉ cần frontend là cần map port ra ngoài vì user sẽ gọi vào từ đó, còn lại tất cả các service khác sẽ giao tiếp container->container bên trogn Docker luôn

Ở trên với service cartservice ta cần set biến môi trường REDIS_ADDR=redis-cart:6379 nó là địa chỉ của redis, mình biết biến này là vì xem ở file manifest K8S kubernetes-manifests/cartservice.yml 😆

Giờ ta chạy lên xem thế nào nhé:

docker compose up -d

Sau đó ta check xem các service đã Up chưa:

docker compose ps

Thì thấy kết quả như sau:

Screenshot 2024-07-06 at 12.10.28 PM.png

Ủa ở đây sao lại có mỗi 5 service Up nhỉ???? 🙄🙄

Trong khi ở docker-compose.yml ta có tất cả 8 services (kể cả redis), tức là ở đây ta thiếu 3 services: paymentservice, currencyservice, cartservice

Giờ ta sẽ check logs các service bị lỗi xem như nào nhé:

docker compose logs paymentservice

Screenshot 2024-07-06 at 12.12.58 PM.png

Lỗi: server must be bound in order to start

Lạ nhỉ??? 🤨🤨

Check code của paymentservice/server.js thì lỗi trả về từ GRPC, lọ mọ search Google thì thấy được issue này: https://github.com/grpc/grpc-node/issues/1404, có vẻ là bị lỗi IP port gì đó

Mở file manifest Kubernetes để hóng xem khi deploy với K8S thì họ có làm gì thêm không:

# kubernetes-manifests/paymentservice.yaml

...
env:
- name: PORT
  value: "50051"
- name: DISABLE_PROFILER
  value: "1"

Ầu, thì ra họ phải set PORT cho paymentservice, bên cạnh đó họ cũng có DISABLE_PROFILER luôn, vậy thì ta cứ follow và thêm vào các biến môi trường giống vậy nhé. Ta sửa lại docker-compose.yml như sau:

services:
  adservice:
    image: adservice
    environment:
      - PORT=9555

  productcatalogservice:
    image: productcatalogservice
    environment:
      - PORT=3550
      - DISABLE_PROFILER=1
  
  cartservice:
    image: cartservice
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart
  
  redis-cart:
    image: redis:6-alpine

  shippingservice:
    image: shippingservice
    environment:
      - PORT=50051
      - DISABLE_PROFILER=1

  currencyservice:
    image: currencyservice
    environment:
      - PORT=7000
      - DISABLE_PROFILER=1

  paymentservice:
    image: paymentservice
    environment:
      - PORT=50051
      - DISABLE_PROFILER=1

  emailservice:
    image: emailservice
    environment:
      - PORT=8080
      - DISABLE_PROFILER=1

Ở trên ta cần check lại từng service một xem chúng cần biến môi trường gì, bên Kubernetes có biến nào ta thêm hết vào nhé 😁

Sau đó ta restart lại project:

docker compose down
docker compose up -d

Sau đó ta lại tiếp tục kiểm tra xem các service đã Up hết chưa:

docker compose ps

Các bạn tự làm phần này nhé, kiểm tra xem đủ 8 services chưa nhé, đến bước này là phải OK rồi đó, trừ các bạn dùng Macbook Apple Silicon chip (chip M) 😢

Với Macbook Apple chip

Nếu các bạn dùng Macbook Apple chip, thì ở bước này ta khi ta chạy docker compose ps, ta mới thấy chỉ có 7 services Up:

Screenshot 2024-07-06 at 12.20.11 PM.png

Thiếu mất một đó là cartservice, check logs ta thấy như sau:

docker compose logs cartservice

Screenshot 2024-07-06 at 12.23.21 PM.png

Search google một chút ra đầy kết quả, lí do là vì khả năng tương thích của project C# (dotnet) trên Apple Chip, vì apple chip họ dùng architecture khác (arm), trong khi thường sẽ là amd

Ta có thể check architecture hệ điều hành của chúng ta với command sau:

arch

-->>>
arm64

Vậy giờ thử chạy cartservice với architecture amd xem, ta update docker-compose.yml cho cartservice như sau:

  cartservice:
    image: cartservice
    platform: linux/amd64 # ==> thêm vào
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart

Sau đó ta restart lại project:

docker compose down
docker compose up -d

Ta lại thấy lỗi khác 😭😭:

Screenshot 2024-07-06 at 12.27.17 PM.png

Lí do là vì ta muốn chạy image cartservice với platform (architecture) khác, trong khi ở local ta không có image được build với platform như vậy nên Docker nó fallback tìm trên Dockerhub và không thấy, do vậy ta cần update Dockerfile của cartservice như sau:

FROM --platform=amd64 mcr.microsoft.com/dotnet/sdk:8.0.302-noble@sha256:bd836d1c4a19860ee61d1202b82561f0c750edb7a635443cb001042b71d79569 as builder
WORKDIR /app
COPY cartservice.csproj .
RUN dotnet restore cartservice.csproj \
    -r linux-x64
COPY . .
RUN dotnet publish cartservice.csproj \
    -p:PublishSingleFile=true \
    -r linux-x64 \
    --self-contained true \
    -p:PublishTrimmed=true \
    -p:TrimMode=full \
    -c release \
    -o /cartservice

# https://mcr.microsoft.com/product/dotnet/runtime-deps
FROM --platform=amd64 mcr.microsoft.com/dotnet/runtime-deps:8.0.6-noble-chiseled@sha256:55d6e41f2e7687c597daa4fdca997b07beb3e23b6283729e19bb8ceb272def1a

WORKDIR /app
COPY --from=builder /cartservice .
EXPOSE 7070
ENV DOTNET_EnableDiagnostics=0 \
    ASPNETCORE_HTTP_PORTS=7070
USER 1000
ENTRYPOINT ["/app/cartservice"]

Ở trên các bạn chú ý mình đã thêm --platform=amd64 vào 2 chỗ có FROM.

Sau đó ta build lại image:

docker build -t cartservice:v1 .

Ở trên mình thêm tag v1 cho khác tránh nhầm lẫn

Nhưng lại có lỗi khác đó là build rất lâu, mãi chưa xong 😰😰:

Screenshot 2024-07-06 at 12.34.10 PM.png

Bị treo luôn ở đoạn RUN dotnet restore....

Lại lọ mọ search Google, mò một lúc thì tìm ra là có lẽ ta cần thêm ENV DOTNET_EnableWriteXorExecute=0, thôi thì lại sửa Dockerfile tiếp:

FROM --platform=amd64 mcr.microsoft.com/dotnet/sdk:8.0.302-noble@sha256:bd836d1c4a19860ee61d1202b82561f0c750edb7a635443cb001042b71d79569 as builder
ENV DOTNET_EnableWriteXorExecute=0
WORKDIR /app
COPY cartservice.csproj .
RUN dotnet restore cartservice.csproj \
    -r linux-x64
COPY . .
RUN dotnet publish cartservice.csproj \
    -p:PublishSingleFile=true \
    -r linux-x64 \
    --self-contained true \
    -p:PublishTrimmed=true \
    -p:TrimMode=full \
    -c release \
    -o /cartservice

# https://mcr.microsoft.com/product/dotnet/runtime-deps
FROM --platform=amd64 mcr.microsoft.com/dotnet/runtime-deps:8.0.6-noble-chiseled@sha256:55d6e41f2e7687c597daa4fdca997b07beb3e23b6283729e19bb8ceb272def1a

WORKDIR /app
COPY --from=builder /cartservice .
EXPOSE 7070
ENV DOTNET_EnableDiagnostics=0 \
    ASPNETCORE_HTTP_PORTS=7070
USER 1000
ENTRYPOINT ["/app/cartservice"]

Ở trên ta đã thêm ENV DOTNET_EnableWriteXorExecute=0 vào stage builder (lần FROM đầu tiên)

Sau đó ta build lại image với tag mới v2:

docker build -t cartservice:v2 .

Oh ngon rồi:

Screenshot 2024-07-06 at 12.39.51 PM.png

Ta update cartservicedocker-compose.yml trước khi chạy lại nhé:

  cartservice:
    image: cartservice:v2 # ==> thêm vào
    platform: linux/amd64 # ==> thêm vào
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart

Sau đó ta restart lại project:

docker compose down
docker compose up -d

Đến giờ thì ta đã có đủ tất cả 8 service đều Up, check logs của cartservice cũng oke rồi:

Screenshot 2024-07-06 at 12.42.42 PM.png

Dockerize lần hai

Lần này ta sẽ deploy 4 service còn lại, bao gồm: recommendation, frontend, checkout, loadgenerator

Cách làm vẫn tương tự, ta mở terminal ở từng service và build:

# src/recommendationservice
docker build -t recommendationservice .

# src/frontend
docker build -t frontend .

# src/checkoutservice
docker build -t checkoutservice .

# src/loadgenerator
docker build -t loadgenerator .

Phần này thì các bạn tự chạy sẽ thấy OK nhé, nhưng vẫn trừ các bạn dùng Macbook Apple Chip 🤣🤣

Với các bạn dùng Apple Chip, khi build tới loadgenerator sẽ gặp lỗi:

Screenshot 2024-07-06 at 12.48.05 PM.png

Phần này thì cách fix giống với cartservice ở trên, ta update lại Dockerfile của loadgenerator như sau:

FROM --platform=linux/amd64 python:3.12.4-slim@sha256:d3a32591680bdfd49da5773495730cf8afdb817e217435db66588b2c64db6d5e as base

FROM base as builder

COPY requirements.txt .

RUN pip install --prefix="/install" -r requirements.txt

FROM base

WORKDIR /loadgen

COPY --from=builder /install /usr/local

# Add application code.
COPY locustfile.py .

# enable gevent support in debugger
ENV GEVENT_SUPPORT=True

ENTRYPOINT locust --host="http://${FRONTEND_ADDR}" --headless -u "${USERS:-10}" 2>&1

Ở trên dòng FROM đầu tiên ta thêm vào --platform=linux/amd64, chú ý rằng ta không cần làm vậy với 2 dòng FROM bên dưới, vì 2 cái FROM bên dưới chúng FROM trực tiếp từ base rồi (là dòng đầu tiên)

Sau khi update thì ta build lại loadgenerator (ta dùng tag v1 cho khác nhé):

docker build -t loadgenerator:v1 .

Oke ngon rồi:

Screenshot 2024-07-06 at 12.50.55 PM.png

Mệt với Apple chip quá 😂😂

Sau khi đã build xong các service ta update lại docker-compose.yml và thêm tất cả các service vào:

services:
  adservice:
    image: adservice
    environment:
      - PORT=9555

  productcatalogservice:
    image: productcatalogservice
    environment:
      - PORT=3550
      - DISABLE_PROFILER=1

  cartservice:
    image: cartservice:v2 # ==> thêm vào
    platform: linux/amd64 # ==> thêm vào
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart

  redis-cart:
    image: redis:6-alpine

  shippingservice:
    image: shippingservice
    environment:
      - PORT=50051
      - DISABLE_PROFILER=1

  currencyservice:
    image: currencyservice
    environment:
      - PORT=7000
      - DISABLE_PROFILER=1

  paymentservice:
    image: paymentservice
    environment:
      - PORT=50051
      - DISABLE_PROFILER=1

  emailservice:
    image: emailservice
    environment:
      - PORT=8080
      - DISABLE_PROFILER=1

# --->> Thêm vào từ đây
  recommendationservice:
    image: recommendationservice
    environment:
      - PORT=8080
      - PRODUCT_CATALOG_SERVICE_ADDR=productcatalogservice:3550
      - DISABLE_PROFILER=1
    depends_on:
      - productcatalogservice

  checkoutservice:
    image: checkoutservice
    environment:
      - PORT=5050
      - PRODUCT_CATALOG_SERVICE_ADDR=productcatalogservice:3550
      - SHIPPING_SERVICE_ADDR=shippingservice:50051
      - PAYMENT_SERVICE_ADDR=paymentservice:50051
      - EMAIL_SERVICE_ADDR=emailservice:8080
      - CURRENCY_SERVICE_ADDR=currencyservice:7000
      - CART_SERVICE_ADDR=cartservice:7070
    depends_on:
      - productcatalogservice
      - shippingservice
      - paymentservice
      - emailservice
      - currencyservice
      - cartservice

  frontend:
    image: frontend
    ports:
      - "8000:8080"
    environment:
      - PORT=8080
      - PRODUCT_CATALOG_SERVICE_ADDR=productcatalogservice:3550
      - CURRENCY_SERVICE_ADDR=currencyservice:7000
      - CART_SERVICE_ADDR=cartservice:7070
      - RECOMMENDATION_SERVICE_ADDR=recommendationservice:8080
      - SHIPPING_SERVICE_ADDR=shippingservice:50051
      - CHECKOUT_SERVICE_ADDR=checkoutservice:5050
      - AD_SERVICE_ADDR=adservice:9555
      - ENABLE_PROFILER=0
      - SHOPPING_ASSISTANT_SERVICE_ADDR=shoppingassistantservice:8080
    depends_on:
      - productcatalogservice
      - currencyservice
      - cartservice
      - recommendationservice
      - shippingservice
      - checkoutservice
      - adservice

  loadgenerator:
    image: loadgenerator:v1
    platform: linux/amd64
    environment:
      - FRONTEND_ADDR=frontend:8080
    depends_on:
      - frontend

Chú ý rằng ở trên các biến môi trường mình xem từ các file manifest Kubernetes của các service tương ứng và thêm vào, mình có thêm depends_on thể hiện sự phụ thuộc giữa các service cho đúng với diagram, như vậy thì khi Docker start container nó sẽ start các service độc lập trước, sau đó tới các service phụ thuộc

Chú ý rằng ở service frontend mình phải thêm biến SHOPPING_ASSISTANT_SERVICE_ADDR, vì trong code họ yêu cầu cái đó, nhưng thực tế ta không cần service đó để chạy

Giờ ta restart lại project nhé:

docker compose down

docker compose up -d

Pòm pòm chíu chíu 🥳🥳:

Screenshot 2024-07-06 at 11.02.27 AM.jpg

App của chúng ta lên rồi, các bạn thoải mái test xem tất cả flow có gì lỗi không nhé:

Screenshot 2024-07-06 at 12.59.55 PM.png

Screenshot 2024-07-06 at 1.00.01 PM.png

Screenshot 2024-07-06 at 1.00.12 PM.png

Với Macbook Apple Chip

Vâng, một lần nữa, lại là Apple Chip 🤣🤣

nếu ta thử restart lại project:

docker compose down

docker compose up -d

Thì rất có thể ta sẽ gặp lỗi:

Screenshot 2024-07-06 at 1.04.42 PM.png

Lại là cartservice, cái service C# Dotnet củ chuối này 🤨🤨

Check log ta thấy như sau:

20240706-123737.jpeg

Sau khi search một vòng Google thì ta sẽ hiểu ra thì đây là một lỗi khá phổ biến của project C#(dotnet) khi chạy trên arm.

Tìm mãi không ra được solution cụ thể, tắt laptop khởi động lại thì có khi được 1-2 lần lại bị.

May quá tìm ra PR này: https://github.com/GoogleCloudPlatform/microservices-demo/pull/2266/files#diff-c9094dcf2dd2b5e3bb57d27631699d50e63b9bfb3aa3665db826e031b0ab9b4c

ý tưởng của họ là update Dockerfile để build cartservice target tới architecture khác là linux-musl-arm64 (alpine + arm64), dùng runtime identifier (RID):

  • linux: hệ điều hành target là Linux
  • musl: Thư viện C là musl, thường được dùng trên bản phân phối Alpine.
  • arm64: architecture la ARM64 (cũng được biết đến là AArch64), tương thích với Appl M1/M2/... chips và các platform ARM64 khác.

Giờ ta sửa lại Dockerfile của cartservice như sau nhé:

FROM mcr.microsoft.com/dotnet/sdk:8.0 as builder
WORKDIR /app
COPY cartservice.csproj .
RUN dotnet restore cartservice.csproj \
    -r linux-musl-arm64
COPY . .
RUN dotnet publish cartservice.csproj \
    -p:PublishSingleFile=true \
    -r linux-musl-arm64 \
    --self-contained true \
    -p:PublishTrimmed=true \
    -p:TrimMode=full \
    -c release \
    -o /cartservice

# https://mcr.microsoft.com/product/dotnet/runtime-deps
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine3.18-arm64v8

WORKDIR /app
COPY --from=builder /cartservice .
EXPOSE 7070
ENV DOTNET_EnableDiagnostics=0 \
    ASPNETCORE_HTTP_PORTS=7070
USER 1000
ENTRYPOINT ["/app/cartservice"]

Ở trên các bạn để ý rằng:

  • ta không cần tới biến môi trường ENV DOTNET_EnableWriteXorExecute=0
  • ở stage builder ta dùng linux-musl-arm64
  • ở cái FROM thứ 2 thì ta dùng image runtime-deps:8.0-alpine3.18-arm64

Giờ ta build lại image cartservice với tag v3 nhé:

docker build -t cartservice:v3 .

Sau đó sửa lại cartservicedocker-compose.yml

  cartservice:
    image: cartservice:v3 # ==> update
    environment:
      - REDIS_ADDR=redis-cart:6379
    depends_on:
      - redis-cart

Chú ý rằng ta đã bỏ đi dòng platform: linux/amd64

Cuối cùng chạy lên ta sẽ thấy OK nhé. phewwwwww Apple Chip mệt quá ta 😅

Tổng hợp và kết bài

Như các bạn thấy, dù bài này Dockerfile họ đã viết sẵn cho chúng ta rồi nhưng khi chạy lên tuỳ vào môi trường của ta là gì nó còn có thể phát sinh lỗi và ta phải mò thêm.

Nhìn chung đây là ví dụ khá là trực quan demo việc deploy microservices với Docker như thế nào. Việc vẽ được, hiểu được architecture trước giúp quá trình làm việc của ta mượt hơn nhiều, ta biết được service nào phụ thuộc vào service khác, service nào không, từ đó đưa ra kế hoạch deploy cho phù hợp.

Chúc các bạn cuối tuần vui vẻ, hẹn gặp lại các bạn ở những bài sau


All rights reserved

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í