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

Optimize Container Image: Tránh copy thủ công file project

Có nhiều cách để optimize container images:

Trong bài viết này, mình sẽ hướng dẫn các bạn cách copy tự động file *.csproj thay vì phải manually. Một là để tránh việc tạo nhiều layer. Hai là hạn chế sai sót trong quá trình copy.
Bạn có thể tham khảo bài viết: https://nhatkyhoctap.blogspot.com/2022/08/docker-tao-docker-file-cho-nhieu.html để lấy source code

Bài toán

Cấu trúc thư mục Project như sau:

📁 containerize-a-net-app
    └──DockerizeMultiProject.sln
    └──📂 DockerizeMultiProject
        ├──DockerizeMultiProject.csproj
        ├──*.*
    └──📂 DockerizeMultiProject.Domain
        ├──DockerizeMultiProject.Domain.csproj
        ├──*.*
    └──📂 DockerizeMultiProject.Infrastructure
        ├──DockerizeMultiProject.Infrastructure.csproj
        ├──*.*

Dockerfile tương ứng như sau:

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env
WORKDIR /app 
#
# copy csproj and restore as distinct layers
COPY *.sln .
# 3 below lines will be replaced
COPY DockerizeMultiProject/*.csproj ./DockerizeMultiProject/
COPY DockerizeMultiProject.Domain/*.csproj ./DockerizeMultiProject.Domain/
COPY DockerizeMultiProject.Infrastructure/*.csproj ./DockerizeMultiProject.Infrastructure/
#
RUN dotnet restore 
#
# copy everything else and build app
COPY . ./
#
WORKDIR /app/DockerizeMultiProject
RUN dotnet publish -c Release -o out 
#
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine
WORKDIR /app 
#
COPY --from=build-env /app/DockerizeMultiProject/out .
ENTRYPOINT ["dotnet", "DockerizeMultiProject.dll"]

Với project đơn giản, bạn có thể thực hiện việc copy thủ công. Nhưng giả sử số lượng project của bạn có từ 50 project trở lên, thì việc làm thủ công này cần cẩn thận và dễ bị sai sót

Để khắc phục, bạn có thể dùng những câu lệnh trong Bash để thực hiện việc copy file.

Note: bạn có thể gõ nhiều dòng trong Bash bằng cách: Sau khi kết thúc 1 dòng, bạn gõ Ctrl + Enter. Cuối cùng bạn gõ Enter để kết thúc.

Dựa vào các câu lệnh trên Bash, có 2 cách như sau: (còn nhiều cách khác nữa mà mình chưa tìm hiểu)

Cách 1: Folder name và Project name giống nhau

Thư mục Project chứa file *.csproj

COPY ./*/*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done

Dòng 1: Thực hiện việc copy toàn bộ file *.csproj vào thư mục WORKDIR 

Dòng 2: Duyệt toàn bộ danh sách file *.csproj. Ở mỗi vòng lặp, thực hiện việc

  • Tạo folder và sub-folder với tham số -p.
  • ${file%.*}: loại bỏ extension ra khỏi đường dẫn file.
    VD: folder-path/abc.csproj => folder-path/abc
  • mv: move file từ WORKDIR vào folder project

Cách 2: Tìm kiếm và copy từng file csproj

Lúc đầu mình có thử cách làm này trong Bash thì chạy được, nhưng khi đưa vào Dockerfile thì gặp vấn đề do WORKDIR trong context nằm đường dẫn khác

RUN for file in $(ls */*.csproj); do mkdir -p ./$(dirname "$file")/ && cp $file ./$file ;done;
Trên Cloudaffaire có hướng dẫn 1 cách như sau: (tương tự cách 1)
COPY *.sln .
COPY */*.csproj ./
RUN find *.csproj | sed -e 's/.csproj//g' | xargs mkdir
RUN find *.csproj | sed -r -e 's/((.+).csproj)/.\/\1 .\/\2/g' | xargs -I % sh -c 'mv %'

Lệnh seq:

$ echo 'DockerizeMultiProject.Domain/abc.csproj' | sed -e 's/.csproj//g'
DockerizeMultiProject.Domain/abc'

-e script, --expression=script
                 add the script to the commands to be executed

$ echo 'DockerizeMultiProject.Domain/abc.csproj' | sed -r -e 's/((.+).csproj)/.\/\1 .\/\2/g'
./DockerizeMultiProject.Domain/abc.csproj ./DockerizeMultiProject.Domain/abc
-E, -r, --regexp-extended use extended regular expressions in the script (for portability use POSIX -E).

Nhận xét

  1. According to Docker's COPY documentation:

    COPY obeys the following rules:

    The path must be inside the context of the build; you cannot COPY ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

    It turns out that you cannot include files outside Docker's build context. However, you can copy files from the Dockerfile's parent directory.

    Trả lờiXóa

Đăng 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.