Chuyển đến nội dung chính

Azure Pipeline: Build & Push Docker Image lên Docker Hub - Day 3

Đây là bài mình vừa học vừa ghi lại trong quá trình thực hành DevOps — từ việc cài Docker Desktop, tạo Dockerfile cho ứng dụng C#, đến việc tự động build và push image lên Docker Hub bằng Azure Pipelines.
Mục tiêu là tự hiểu – tự làm – tự note, để khi quay lại sau này có thể triển khai lại toàn bộ mà không cần tìm lại tài liệu.

Giới thiệu 

Trong DevOps, Docker Image là “bản đóng gói” (package) toàn bộ ứng dụng, môi trường và dependency.
Khi bạn build một image, bạn đang tạo ra một “snapshot” mà có thể chạy ở bất kỳ môi trường nào — từ máy local đến cloud.

Quy trình chuẩn để đưa image lên cloud registry gồm 3 bước:

  • Build image – dùng Dockerfile.
  • Tag image – đặt tên định danh (vd: username/app:latest).
  • Push image – đẩy lên Docker Hub (hoặc ACR, ECR...).

Với Azure Pipelines, ta có thể tự động hoá toàn bộ quy trình đó bằng một YAML pipeline.

Chuẩn bị

  • Self-hosted agent: Xem lại Day 2
  • Docker Desktop for Windows

Kiểm tra lại Docker:

docker version
docker info
Nếu có thông tin client/server thì Docker CLI đã sẵn sàng.

Tạo Dockerfile

Đặt Dockerfile ở thư mục gốc của Project
# Stage 1: Build .NET app
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY HelloWorldApp/*.csproj HelloWorldApp/
RUN dotnet restore HelloWorldApp/HelloWorldApp.csproj
COPY . .
RUN dotnet publish HelloWorldApp/HelloWorldApp.csproj -c Release -o /app/publish

# Stage 2: Runtime
FROM mcr.microsoft.com/dotnet/runtime:9.0
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "HelloWorldApp.dll"]

Build và push Docker image

Trong Azure DevOps:

  • Vào Project Settings → Service Connections → New service connection
  • Chọn Docker Registry
  • Điền:
    • Registry type: Docker Hub
    • Registry URL: https://index.docker.io/v1/
    • Username: tài khoản Docker Hub
    • Password/Token: Docker Hub Access Token (an toàn hơn password)
  • Đặt tên: dockerhub-conn

Viết Pipeline YAML

Tạo file azure-pipelines-docker.yml trong repo

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger: none

pool:
  name: Default
  demands:
  - Agent.Name -equals MySelfHostedAgent-ABT
  - docker

variables:
  imageName: 'yourdockerhubuser/helloworld'

steps:
- checkout: self

- task: PowerShell@2
  displayName: 'Check Docker environment'
  inputs:
    targetType: inline
    script: |
      docker version
      docker info

- task: Docker@2
  displayName: 'Build and Push image to Docker Hub'
  inputs:
    containerRegistry: 'dockerhub-conn'  # service connection to Docker Hub
    repository: '$(imageName)'
    command: 'buildAndPush'
    Dockerfile: '**/Dockerfile'
    tags: |
      $(Build.SourceVersion)
      latest

Lưu ý

  • Docker@2 nghĩa là dùng Docker task, version 2, do Microsoft cung cấp sẵn, tương đương việc chạy các lệnh Docker CLI (docker build, docker push) nhưng được đóng gói lại, dễ quản lý và tái sử dụng.
  • containerRegistry: 'dockerhub-conn'
    Đây là Service Connection bạn đã tạo trong Azure DevOps (mục Project Settings → Service connections).
    dockerhub-conn chứa thông tin đăng nhập Docker Hub (username + access token).
    Khi chạy pipeline, Azure DevOps tự docker login vào Docker Hub bằng connection này.
  •  repository: '$(imageName)': repository là tên repo trên Docker Hub nơi image sẽ được push lên.
  •  Dấu $() gọi là Azure Pipeline variable syntax.
  •  command: 'buildAndPush': Là chế độ hoạt động của Docker task.
    buildAndPush =
docker build -t <imageName>:<tag> .
docker push <imageName>:<tag>
  • Dockerfile: '**/Dockerfile': chỉ đường dẫn đến Dockerfile để task biết nơi build. **/Dockerfile là pattern tìm kiếm đệ quy (glob pattern), tìm trong tất cả thư mục con.
  •  tags: |
    Đây là danh sách tag gắn cho image khi build/push lên Docker Hub. Dấu | cho phép viết nhiều dòng
  • $(Build.SourceVersion): biến hệ thống mặc định của Azure Pipelines, chứa mã commit SHA đầy đủ (40 ký tự) của lần chạy pipeline đó

 Ví dụ nếu bạn vừa commit lên branch main:

commit 9f1e27ac4d87b63c8d2f1b8d0e8212cf3e39aabc
trong pipeline:
$(Build.SourceVersion) = 9f1e27ac4d87b63c8d2f1b8d0e8212cf3e39aabc
Khi build image, tag của bạn sẽ là:
yourdockerhubuser/helloworld:9f1e27ac4d87b63c8d2f1b8d0e8212cf3e39aabc
giúp truy vết chính xác image đó build từ commit nào.

Bạn cũng có thể rút gọn tag bằng:

tags: |
  $(Build.SourceVersion:0:7)
  latest

→ chỉ lấy 7 ký tự đầu của SHA (ví dụ: 9f1e27a). 

Kết quả Pipline

 * branch            9a4bb752fa16b15c936a5585019815925edd73aa -> FETCH_HEAD
git checkout --progress --force refs/remotes/origin/9a4bb752fa16b15c936a5585019815925edd73aa
Note: switching to 'refs/remotes/origin/9a4bb752fa16b15c936a5585019815925edd73aa'.
...
REPOSITORY                         TAG                                        IMAGE ID       CREATED                  SIZE
***/helloworld             9a4bb752fa16b15c936a5585019815925edd73aa   67592544cf34   Less than a second ago   293MB
***/helloworld             latest                                     67592544cf34   Less than a second ago   293MB

Hiểu về Task trong Azure Pipeline

Một Task là đơn vị công việc (step) trong pipeline — mỗi task có nhiệm vụ riêng biệt.

Cấu trúc

- task: <task-name>@<version>
  displayName: <description>
  inputs:
    <tham_số>: <value>

Task: PowerShell@2

PowerShell@2 là task dùng để chạy câu lệnh hoặc script PowerShell trên agent. Phù hợp cho các bước kiểm tra môi trường, thao tác file, gọi công cụ CLI, hoặc thực hiện các logic tùy biến trong pipeline.

Task: Docker@2

Docker@2 là task chuyên dụng cho các thao tác Docker như login, build, tag, push, và buildAndPush. Kết hợp với Service Connection để xác thực an toàn với Docker Hub (hoặc registry khác).

Một số task khác hay dùng

  • Checkout — Lấy source code từ repository vào agent workspace để các bước sau sử dụng.
  • DotNetCoreCLI@2 — Thực thi các lệnh .NET (restore, build, test, publish) dành cho ứng dụng .NET Core/.NET.
  • Bash@3 — Chạy shell script trên agent Linux/macOS; hữu ích khi cần môi trường POSIX hoặc lệnh đặc thù Unix.
  • CmdLine@2 — Chạy lệnh dòng lệnh thuần (cmd) trên Windows agent; thích hợp cho các công cụ không cần Power

Xóa Docker Image để giải phóng dung lượng

Sau một thời gian sử dụng, bạn có thể có hàng chục image cũ không còn dùng đến — đặc biệt khi thường xuyên build hoặc pull từ registry.

Những image này chiếm rất nhiều dung lượng, đôi khi lên đến vài GB.
Dưới đây là các cách dọn dẹp image hiệu quả

docker system df -v
-v nghĩa là hiển thị chi tiết từng phần tử

 

Tham khảo

https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/containers/push-image?view=azure-devops&tabs=yaml&pivots=docker-registry 


Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.