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

Docker: Khám phá quá trình build 1 image - Part 3

Trong bài viết này, chúng ta sẽ tìm hiểu 3 cách tối ưu: Layer Caching, dockerignore, và multi-stage

Docker layer caching

Docker layer caching (DLC) là một tính năng rất quan trọng giúp giảm thời gian của quá trình build bằng cách tận dụng những layer đã được build từ lần trước đó.
Để có thể tận dụng tối đa tính năng này, chúng ta cần sắp xếp lại và tách lệnh build sao cho phần lệnh ít thay đổi sẽ nằm ở trên, phần thay đổi thường xuyên sẽ nằm ở dưới.
Quay lại với ví dụ ExpressJs, giả sử chúng ta thêm 1 dòng console trong source code (Xem lại ví dụ ở Part 1)

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Nei hou!')
})

console.log("test");

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
Quá trình build
$ docker build -t alpine-test .
Sending build context to Docker daemon   2.43MB
Step 1/5 : FROM node:alpine
 ---> 5e67b1710572
Step 2/5 : WORKDIR /usr/app
 ---> Using cache
 ---> 4f036c778fe7
Step 3/5 : COPY ./ /usr/app/
 ---> f7a6b9681a06
Step 4/5 : RUN npm install
 ---> Running in 41ab0bba5814

up to date, audited 58 packages in 842ms

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Removing intermediate container 41ab0bba5814
 ---> 13605717f2ac
Step 5/5 : CMD ["npm", "start"]
 ---> Running in fdf9ba2a93e0
Removing intermediate container fdf9ba2a93e0
 ---> 985b206362eb
Successfully built 985b206362eb
Successfully tagged alpine-test:latest

Chú ý là từ đoạn image 4f036c778fe7 trở lên trên, Docker daemon sẽ lấy từ cache. Bắt đầu từ step 3, image sẽ được tạo mới thay vì lấy từ cache. Rất hợp lý vì mình đã thay đổi source code. 


Do vậy, trong quá trình build, chúng ta sẽ đưa các thành phần ít thay đổi lên trên.

Sử dụng .dockerignore

File .dockerignore giúp bạn định nghĩa những file hoặc thư mục mà bạn cần bỏ qua để build image. Việc này giúp giảm kích thước Docker image và tăng tốc độ quá trình build image. Dưới đây là cú pháp cho file .dockerignore:
pattern:
{ term }
term:
'*' matches any sequence of non-Separator characters
'?' matches any single non-Separator character
'[' [ '^' ] { character-range } ']'
character class (must be non-empty)
c matches character c (c != '*', '?', '\\', '[')
'\\' c matches character c

character-range:
c matches character c (c != '\\', '-', ']')
'\\' c matches character c
lo '-' hi matches character c for lo <= c <= hi

additions:
'**' matches any number of directories (including zero)
'!' lines starting with ! (exclamation mark) can be used to make exceptions to exclusions
'#' lines starting with this character are ignored: use it for comments
Dockerignore cho Angular:
node_modules
npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode
Ví dụ file dockerignore cho asp.net core
# Created by https://www.gitignore.io/api/csharp

### Csharp ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/
Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/
tools/Cake.CoreCLR
.vscode
tools
.dotnet
Dockerfile

# .env file contains default environment variables for docker
.env
.git/

Multi Stage

Chúng ta sẽ minh họa bằng App Angular. Khác với ExpressJs, Angular cần được build và như vậy sẽ dễ hình dung hơn. Thay vì sử dụng NodeJs để host website, chúng ta sử dụng NGINX.

NGINX là một web server mạnh mẽ mã nguồn mở. Nginx sử dụng kiến trúc đơn luồng, hướng sự kiện vì thế nó hiệu quả hơn Apache server. Nó cũng có thể làm những thứ quan trọng khác, chẳng hạn như load balancing, HTTP caching, hay sử dụng như một reverse proxy.

Để hiển thị Syntax Highlighter trong Visual Studio Code, bạn cài đặt extension NGINX: ext install vscode-ngin.

Trong Terminal, tạo project Hello-World bằng cách

ng new hello-world

Tạo Dockerfile

Chúng ta sẽ có 2 stage để build 1 application Angular:

  • Stage 1: Sử dụng base image Node để install packages, copy file thư mục output
  • Stage 2: Sử dụng 1 base image v2 dùng Nginx.

 Do ứng dụng Angular tương đối nặng, và đòi hỏi cần build typescript, nên chúng ta cần chuẩn bị file .dockerignore để loại bỏ bớt 1 số folder như /nodemodules, .vscode...

Ngoài ra để cấu hình nginx, chúng ta xây dựng file nginx.config.

Các bạn lưu ý file Dockerfile, .dockerignore đều nằm ở vị trí ngang hàng với thư mục source.

📁 frontend
    └── 📂 angular
    └──📂 .vscode
    └──📂 nodemodules
    └──📂 *.*
    └──📂 src
        ├──index.html
        ├──*.*
    └──.dockerignore
    └──Dockerfile
    └──nginx.conf
    └──package.json
    └──package-lock.json
    └──*.*
File .dockerignore

.git
/node_modules
.gitignore
/e2e
File nginx.config
events{}

http {    
        include /etc/nginx/mime.types;    
server {   
        listen 80;
        server_name localhost;
        root /usr/share/nginx/html;
        index index.html;        
location / {
            try_files $uri $uri/ /index.html;
        }
    }
}
Trong file Dockerfile, chúng ta sử dụng 2 images: node:18-alpine3.15: dùng để phục vụ cho install package, copy file, và build project. nginx:1.23.1-alpine: dùng để host ứng dụng Angular
### STAGE 1: Build ###
FROM node:18-alpine3.15 AS build
ARG CONFIGURATION='production'

WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
# Build the application
RUN npm run build --  --output-path=dist --configuration=$CONFIGURATION --output-hashing=all


### STAGE 2: Run ###
FROM nginx:1.23.1-alpine
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
# Copy nginx config file
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/dist /usr/share/nginx/html

# Start NgInx service
CMD ["nginx", "-g", "daemon off;"]

Giải thích quá trình build image

Ở đây, chúng ta sử dụng toàn bộ OS là Alpine. Nếu các bạn sử dụng node:latest thì sẽ dụng phiên bản Debian 


Sau khi thực hiện việc copy package.json,chúng ta sẽ install package.

Rồi thực hiện quá trình publish ra folder dist

Các câu lệnh dùng để build, run và exec vào bash:
docker build -t angular-demo .
docker run -d -p 3000:80 --name angular-demo angular-demo
docker exec -it angular-demo sh
Dung lượng file sau khi build:
angular-demo   latest          c35e7f6387b7   22 minutes ago   23.8MB
<none>         <none>          20699e47bc8e   22 minutes ago   607MB
node           18-alpine3.15   ec9347a9b50f   4 days ago       167MB
nginx          1.23.1-alpine   804f9cebfdc5   4 weeks ago      23.5MB

Như vậy là chúng ta đã tối ưu được dung lượng file từ 607MB xuống còn 23.8MB

Hi vọng với bài viết này sẽ hữu ích với các bạn trong quá trình xây dựng build image.

Tham khảo

https://medium.com/the-agile-crafter/docker-image-optimization-from-1-16gb-to-22-4mb-53fdb4c53311

Nhận xét

  1. Docker Image Optimization Tools

    Following are some of the open-source tools that will help you optimize

    Dive: It is an image explorer tool that helps you discover layers in the Docker & OCI containers images. Using dive, you can find ways to optimize your Docker images. Check out the Dive Github repo for more details.
    Docker Slim: It helps you optimize your Docker images for security and size. Check out the Docker Slim Github repo for more details.

    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.