PREV POST 兒子滿 2 歲生日
PUBLIC DATE:2021.09.02
B-09202110安裝 Docker
Docker 架構
Docker 包括三個基本概念:
01. | 鏡像(Image) Docker 鏡像(Image),就相當於是一個 root 文件系統。比如官方鏡像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系統的 root 文件系統。 |
02. | 容器(Container) 鏡像(Image)和容器(Container)的關係,就像是面向對象程序設計中的類和實例一樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等。 |
03. | 倉庫(Repository) 倉庫可看成一個代碼控制中心,用來保存鏡像。 |
Docker 使用客戶端-服務器(C/S)架構模式,使用遠程API來管理和創建Docker容器。
Docker 容器通過 Docker 鏡像來創建。
容器與鏡像的關係類似於面向對象編程中的對象與類。
Docker | 面相對象 |
容器 | 對象 |
鏡像 | 類 |
01. | Docker 鏡像(Images) Docker 鏡像是用於創建 Docker 容器的模板,比如 Ubuntu 系統。 |
02. | Docker 容器(Container) 容器是獨立運行的一個或一組應用,是鏡像運行時的實體。 |
03. | Docker 客戶端(Client) Docker 客戶端通過命令行或者其他工具使用 Docker SDK 與 Docker 的守護進程通信。 |
04. | Docker 主機(Host) 一個物理或者虛擬的機器用於執行 Docker 守護進程和容器。 |
05. | Docker 註冊區(Registry) Docker 倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。Docker Hub 提供了龐大的鏡像集合供使用。 一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個鏡像。 通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標籤就常用於對應該軟件的各個版本。 我們可以通過 <倉庫名>:<標籤> 的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標籤,將以 latest 作為默認標籤。 |
06. | Docker 虛擬平台(Machine) Docker Machine 是一個簡化 Docker 安裝的命令行工具,通過一個簡單的命令行即可在相應的平台上安裝 Docker。 比如 VirtualBox、 Digital Ocean、Microsoft Azure。 |
Docker 常用 CLI
以下為 Docker 平時常用 CLI,並非所有。更多 CLI 請查閱:Docker CLI
※※※※※ 注意事項 ※※※※※
以下的 {machine-name} 在 Docker 裡預設名稱皆為 default。
01. | docker-machine create -d virtualbox {machine-name} 建立 Docker 虛擬平台。(建立在 virtualbox VM 底下) |
02. | docker-machine rm {machine-name} 移除 Docker 虛擬平台。 |
03. | docker-machine env {machine-name} 查看 Docker 虛擬平台對應的環境參數。 |
04. | eval $(docker-machine env) export 環境參數,運行後將會連線到此虛擬機上。 |
05. | docker-machine ls 列出所有 Docker 虛擬平台。 |
06. | docker-machine start {machine-name} 運行所有或指定的 Docker 虛擬平台。 |
07. | docker-machine stop {machine-name} 停止所有或指定的 Docker 虛擬平台。 |
08. | docker-machine restart {machine-name} 重新運行所有或指定的 Docker 虛擬平台。 |
09. | docker build [-t {image}:{version}|-f {Dockerfile Path}|options...] . [--no-cache|options...] 建立 Image。 -t:Image 標籤;-f:指定 Dockerfile 文件所在位置。 ' . ' 為 Docker Image 本地,非電腦本地。 --no-cache:不使用內存建立。 |
10. | docker images [options...] 列出所有 Images。 |
11. | docker rmi {image} 移除 Image。 |
12. | docker ls [-a|options...] 列出所有 Containers。 |
13. | docker rm [{container}|$(docker ps -a -q)] 卸除所有或指定的 Container。 |
14. | docker volume ls [-a|options...] 列出所有 Volumes。 |
15. | docker volume create [options...] [volume] 建立 Volume。 |
16. | docker volume rm [options...] {volume...} 移除 Volume。 |
17. | docker network ls [options...] 列出所有 Network。 |
18. | docker network create [options...] {network} 新增 Network。 |
19. | docker network rm {network} 移除 Network。 |
20. | docker run [options...] {image} [command...] [arg...] 建立 Container ,加入運行命令。 |
21. | docker start [options...] {container...} 運行 Container。 |
22. | docker stop [options...] {container...} 停止 Container。 |
23. | docker restart [options...] {container...} 重新運行 Container。 |
24. | docker exec [options...] {container...} [command...] [arg...] 正在運行的 Container 中運行命令。 |
25. | docker logs [options...] {container...} 打印 Container 的日誌。 ※ 需 Container 運行中才能運作。 |
額外補充 Docker CLI:
01. | docker system df 檢視 Docker 的磁碟使用情況。(類似於 Linux 上的 df 命令) |
02. | docker system prune [-a|options...] 清理磁碟,刪除所有的 Image 、關閉的 Containers、無使用的 Volumes (為 dangling=true,使用中的 Volumes還是會保留。如要刪除,需額外運行下方第 5 點) 和 Networks 。 |
03. | docker ps -a | grep 'Exit' | awk '{print $1}' | xargs docker rm 刪除所有未運行的 Containers。 |
04. | docker rmi $(docker images | grep "^" | awk "{print $3}") 刪除所有 Images(即為 ,無 tag 的 Image)。 |
05. | docker volume rm $(docker volume ls -q) 刪除所有 Volumes。 |
05. | docker volume rm $(docker volume ls -q --filter dangling=true) 刪除所有無使用的 Volumes。 |
Docker Compose 常用 CLI
以下為 Docker Compose 平時常用 CLI,並非所有。更多 CLI 請查閱:Docker Compose CLI
※※※※※ 注意事項 ※※※※※
Docker Compose 會默認 docker-compose 為預設檔名。
建立專案時,docker-compose.yml 文件須放在【根目錄】。
01. | docker-compose build [-f {docker-compose.yml Path}|options...] [--no-cache|options...] 建立由 docker-compose.yml 文件所引入 Dockerfile 方式建立 Image。 -f:指定 docker-compose.yml 文件所在位置。 --no-cache:不使用內存建立。 |
02. | docker-compose up [-f {docker-compose.yml Path}|options...] [-d|options...] [--build|options...] 建立由 docker-compose.yml 文件所有 Images(不建立 Dockerfile 方式)與 Containers。且並運行 Containers。 -f:指定 docker-compose.yml 文件所在位置;-d:背景執行;--build:會建立 Dockerfile 方式。 |
03. | docker-compose start [options...] {container...} 運行由 docker-compose.yml 文件建立所有或指定的 Container。 |
04. | docker-compose stop [options...] {container...} 停止由 docker-compose.yml 文件建立所有或指定的 Container。 |
05. | docker-compose restart [options...] {container...} 重新運行由 docker-compose.yml 文件建立所有或指定的 Container。 |
06. | docker-compose down [options...] 卸除由 docker-compose.yml 文件建立所有的 Container。 |
07. | docker-compose logs [options...] 打印由 docker-compose.yml 文件建立所有 Container 的日誌。 ※ 需 Container 運行中才能運作。 |
.dockerignore / Dockerfile / docker-compose.yml - 配置範例
以下範例為當時所做前後端為 Nuxt.js 專案與 Server 的配置。
而我這裡的配置為區分【開發 / 測試】與【生產】兩種,僅供參考。
更多配置設定:.dockerignore、Dockerfile、docker-compose.yml
專案目錄文件樹狀結構
my-app
┣ app
┣ docker
┣ mariaDB
┣ nginx
┣ nodejs
┣ Dockerfile
┗ Dockerfile.prod
┗ phpmyadmin
┣ .dockerignore
┣ docker-compose.yml
┗ docker-compose.prod.yml
.dockerignore
.dockerignore 文件的用意是當我們在 docker build 的過程中,首先會將指定的上下文目錄打包傳遞給 docker引擎,而這個上下文目錄中可能並不是所有的文件我們都會在 Dockerfile 中使用到,那麼這個時候就可以在 .dockerignore 文件中指定在傳遞給 docker 引擎 時需要忽略掉的文件或文件夾。
比如我們在前端項目中,node_modules 文件夾在構建鏡像過程中如果用不到,但是又異常龐大,那麼向 docker 引擎 傳遞其實是並沒有必要的(可以提升鏡像構建速度),這個時候就可以將 node_modules 文件夾加入 .dockerignore 文件中。
※※※※※ 注意事項 ※※※※※
建立專案時,.dockerignore 文件須放在【根目錄】。
**/.vscode
**/.DS_Store
*.log
Dockerfile*
docker-compose*
.dockerignore
**/.git
.git
.gitignore
**/node_modules
npm-debug*
**/.nuxt
Dockerfile
Dockerfile 是一個用來構建鏡像的文本文件。
※※※※※ 注意事項 ※※※※※
建立專案時,如未採用 docker-compose 方式配置,Dockerfile 文件須放在【根目錄】。
相反的,如有配置 docker-compose ,Dockerfile 可以指向專案內的其它路徑。
在 Dockerfile 文件有中文註解時,在運行中會導致編碼錯誤,建議註解不輸入任何中文或中文標點符號。
● ./docker/nodejs/Dockerfile(開發 / 測試):
# Build Node.js Image
FROM node:14-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Node.js package.json
# COPY /app/package*.json /app/yarn.lock .
# COPY ["/app/package*.json", "/app/yarn.lock", "./"]
COPY /app/package*.json .
RUN yarn install && \
yarn cache clean
# Node.js Plugins
COPY /docker/nodejs/perfect-scrollbar/perfect-scrollbar.css ./node_modules/perfect-scrollbar/css/perfect-scrollbar.css
COPY /docker/nodejs/perfect-scrollbar/perfect-scrollbar.esm.js ./node_modules/perfect-scrollbar/dist/perfect-scrollbar.esm.js
COPY /docker/nodejs/froala-editor/froala_editor.min.js ./node_modules/froala-editor/js/froala_editor.min.js
COPY /docker/nodejs/froala-editor/froala_editor.pkgd.min.js ./node_modules/froala-editor/js/froala_editor.pkgd.min.js
COPY /docker/nodejs/froala-editor/zh_tw.js ./node_modules/froala-editor/js/languages/zh_tw.js
# ENV
ENV NODE_ENV development
ENV TZ Asia/Taipei
EXPOSE 3000
CMD [ "yarn", "dev" ]
● ./docker/nodejs/Dockerfile(生產):
# Build Node.js Image
FROM node:14-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Node.js package.json
# COPY /app/package*.json /app/yarn.lock .
# COPY ["/app/package*.json", "/app/yarn.lock", "./"]
COPY /app/package*.json .
# For Ubuntu
# RUN apt-get update
RUN yarn install && \
yarn cache clean
# APP
COPY /app .
# Node.js Plugins
COPY /docker/nodejs/perfect-scrollbar/perfect-scrollbar.css ./node_modules/perfect-scrollbar/css/perfect-scrollbar.css
COPY /docker/nodejs/perfect-scrollbar/perfect-scrollbar.esm.js ./node_modules/perfect-scrollbar/dist/perfect-scrollbar.esm.js
COPY /docker/nodejs/froala-editor/froala_editor.min.js ./node_modules/froala-editor/js/froala_editor.min.js
COPY /docker/nodejs/froala-editor/froala_editor.pkgd.min.js ./node_modules/froala-editor/js/froala_editor.pkgd.min.js
COPY /docker/nodejs/froala-editor/zh_tw.js ./node_modules/froala-editor/js/languages/zh_tw.js
# ENV
ENV NODE_ENV production
ENV TZ Asia/Taipei
RUN yarn build
EXPOSE 3000
CMD [ "yarn", "start" ]
docker-compose
docker-compose 是用於定義和運行多容器 Docker 應用程序的工具。通過 Compose,您可以使用 YML 文件來配置應用程序需要的所有服務。然後,使用一個命令,就可以從 YML 文件配置中創建並啟動所有服務。
※※※※※ 注意事項 ※※※※※
建立專案時,docker-compose 文件須放在【根目錄】。
● ./docker-compose.yml(開發 / 測試):
# Docker Compose文件版本支持特定的 Docker 版本
version: '3.7'
# external 設為 true 則表示服務用的網絡是用外部的網路,並且搜尋名稱為「my-dns-network」
# 搜尋成功後會自動與 Image 有標示「networks:my-dns-network」服務相連
# 若搜尋失敗,則會顯示以下錯誤:
# ERROR: Please create the network manually using `docker network create my-dns-network` and try again.
networks:
my-dns-network:
external: true
# 新增建立全域的 Volumes 給 Container 使用
volumes:
mariadb_data:
phpmyadmin_data:
# 定義應用服務啟動時,執行 container 的相關資訊
services:
# Development開發環境
# 瀏覽器熱加載,在 nuxt.config.js 加入以下:
# watchers: {
# webpack: {
# poll: true
# }
# }
nuxtjs:
# 使用 Dockerfile 來建立(客製化)
build:
# 構建上下文路徑(.為主目錄)
context: .
# Dockerfile 文件路徑(${PWD}為顯示當前的絕對路徑)
dockerfile: ${PWD}/docker/nodejs/Dockerfile
# Container 名稱(--name {Container名稱})
container_name: c_nuxtjs
# 這兩項是執行 docker-compose 時的參數,分別對應到 Docker 的指令就會是
# -t, --tty # interactive
# -i, --interactive # stdin
# 也就是為執行中的 Container 開啟 Interactive shell,讓使用者可以進入 Container 進行操作
# Container 的標準輸入保持打開(同指令-i|--interactive)
stdin_open: true
# 告訴 Docker 要分配一個虛擬終端機(pseudo-tty)並綁定到 Container 的標準輸入上(-t|--tty)
tty: true
# 設置容器重新啟動事件
# no:是默認的重啟策略,在任何情況下都不會重啟容器
# always:容器總是重新啟動
# on-failure:在容器非正常退出時(退出狀態非 0),才會重啟容器
# unless-stopped:在容器退出時總是重啟容器,但是不考慮在 Docker 守護進程啟動時就已經停止了的容器
restart: always
# 要導出的 Port,可以是 Host:Container,或只指定 Container,這時會隨機挑一個 Host Port 來用
# Port指定建議使用字串,因 YAML 解析器在你挑的 Port 小於 60 時會出問題
ports:
- "3000:3000"
# 鏡射複製、覆蓋、同步目錄文件
# 設定 Container 要使用的 Volumes,可以是一個路徑或是參考到最外層 Volumes 的設定,格式為 Host:Container,你也可以只寫 Container,讓 Docker 自動幫你建立一個
# 注意:如環境為 VM,專案目錄(目錄名稱:nuxt-app)須在VM裡選「設定值或按右鍵」→「共用資料夾」新增機器資料夾,選擇專案目錄路徑,並勾選「自動掛載」、「設為永久」
# 教學:https://stackoverflow.com/questions/45972812/are-you-trying-to-mount-a-directory-onto-a-file-or-vice-versa
volumes:
# 專案目錄文件
- /my-app/app:/usr/src/app
# 使用 Image 內的 node_modules,不使用本機專案 node_modules
- /usr/src/app/node_modules
# 訪問其它容器(定義service之間的相依性)
# 當下 docker-compose up 指令時,mariadb service 會先啟動,然後在啟動 nuxtjs service
depends_on:
- mariadb
# 設定 Container 要加入哪個網路,這邊的項目會參考到最外層 networks 的設定
networks:
- my-dns-network
mariadb:
# 指定 Container 要啟動的 Image
image: mariadb:latest
container_name: c_mariadb
stdin_open: true
tty: true
restart: always
ports:
- "3306:3306"
# 定義環境變數
# 如果值為布林,需用單引號包,如 'true'、'false' 否則 YAML 解析器會把它變為 True 或是 False
environment:
MYSQL_ROOT_PASSWORD: my-password
# MYSQL_DATABASE: my-db
# MYSQL_ROOT_PASSWORD: password
# MYSQL_USER: admin
# MYSQL_PASSWORD: password
volumes:
# 將 mariadb_data volume 映射到 /var/lib/mysql/
- mariadb_data:/var/lib/mysql/
networks:
- my-dns-network
phpmyadmin:
image: phpmyadmin/phpmyadmin:fpm-alpine
container_name: c_phpmyadmin
stdin_open: true
tty: true
restart: always
environment:
# 當設置為 1 連接到任何伺服器時將被允許(phpmyadmin 頁面伺服器欄位為 Mariadb container names)
- PMA_ARBITRARY=1
# 運行 Mariadb 的主機名或 IP
- PMA_HOST=mariadb
# 運行 Mariadb 的 Port
- PMA_PORT=3306
# Nginx 反向代理(避免 phpMyAdmin 登入、登出網址無 pma/,直接顯示 404 如 pma/ 要修改其它名稱時,也得修改 Nginx config 設定檔中的 location)
- PMA_ABSOLUTE_URI=http://my-dns.com/pma/
volumes:
# 將 phpmyadmin_data volume 映射到 /var/www/html/
- phpmyadmin_data:/var/www/html/
# 新增暗色主題介面
- /my-app/docker/phpmyadmin/themes/darkwolf:/var/www/html/themes/darkwolf
depends_on:
- mariadb
networks:
- my-dns-network
nginx:
image: nginx:alpine
container_name: c_nginx
stdin_open: true
tty: true
restart: always
ports:
- "80:80"
volumes:
# Nginx config 設定檔
- /my-app/docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
# 將 phpmyadmin_data volume 映射到給 Nginx 使用
- phpmyadmin_data:/var/www/html/:ro
# 將新增暗色主題介面映射到給 Nginx 使用
- /my-app/docker/phpmyadmin/themes/darkwolf:/var/www/html/themes/darkwolf:ro
depends_on:
- nuxtjs
- mariadb
- phpmyadmin
networks:
- my-dns-network
● ./docker-compose.prod.yml(生產):
# Docker Compose 文件版本支持特定的 Docker 版本。
version: '3.7'
# external 設為 true 則表示服務用的網絡是用外部的網路,並且搜尋名稱為「my-dns-network」。
# 搜尋成功後會自動與 Image 有標示「networks:my-dns-network」服務相連。
# 若搜尋失敗,則會顯示以下錯誤:
# ERROR: Please create the network manually using `docker network create my-dns-network` and try again.
networks:
my-dns-network:
external: true
# 新增建立全域的 Volumes 給 Container 使用
volumes:
mariadb_data:
phpmyadmin_data:
# 定義應用服務啟動時,執行 container 的相關資訊。
services:
# Production上線環境
nuxtjs:
# 使用 Dockerfile 來建立(客製化)
build:
# 構建上下文路徑(.為主目錄)
context: .
# Dockerfile 文件路徑。(${PWD}為顯示當前的絕對路徑)
dockerfile: ${PWD}/docker/nodejs/Dockerfile.prod
# Container 名稱(--name {Container名稱})
container_name: c_nuxtjs
# 這兩項是執行 docker-compose 時的參數,分別對應到 Docker 的指令就會是
# -t, --tty # interactive
# -i, --interactive # stdin
# 也就是為執行中的 Container 開啟 Interactive shell,讓使用者可以進入 Container 進行操作。
# Container 的標準輸入保持打開(同指令-i|--interactive)
stdin_open: true
# 告訴 Docker 要分配一個虛擬終端機(pseudo-tty)並綁定到 Container 的標準輸入上(-t|--tty)
tty: true
# 設置容器重新啟動事件
# no:是默認的重啟策略,在任何情況下都不會重啟容器。
# always:容器總是重新啟動。
# on-failure:在容器非正常退出時(退出狀態非 0),才會重啟容器。
# unless-stopped:在容器退出時總是重啟容器,但是不考慮在 Docker 守護進程啟動時就已經停止了的容器。
restart: always
# 要導出的 Port,可以是 Host:Container,或只指定 Container,這時會隨機挑一個 Host Port 來用。
# Port 指定建議使用字串,因 YAML 解析器在你挑的 Port 小於 60 時會出問題。
ports:
- "3000:3000"
# 鏡射複製、覆蓋、同步目錄文件。
# 設定 Container 要使用的 Volumes,可以是一個路徑或是參考到最外層 Volumes 的設定,格式為 Host:Container,你也可以只寫 Container,讓 Docker 自動幫你建立一個。
# 注意:如環境為 VM,專案目錄(目錄名稱:nuxt-app)須在 VM 裡選「設定值或按右鍵」→「共用資料夾」新增機器資料夾,選擇專案目錄路徑,並勾選「自動掛載」、「設為永久」。
# 教學:https://stackoverflow.com/questions/45972812/are-you-trying-to-mount-a-directory-onto-a-file-or-vice-versa
volumes:
# 使用 Image 內的 node_modules,不使用本機專案 node_modules
- /usr/src/app/node_modules
depends_on:
- mariadb
# 設定 Container 要加入哪個網路,這邊的項目會參考到最外層 networks 的設定。
networks:
- my-dns-network
mariadb:
# 指定 Container 要啟動的 Image
image: mariadb:latest
container_name: c_mariadb
stdin_open: true
tty: true
restart: always
ports:
- "3306:3306"
# 定義環境變數
# 如果值為布林,需用單引號包,如 'true'、'false' 否則 YAML 解析器會把它變為 True 或是 False
environment:
MYSQL_ROOT_PASSWORD: my-password
# MYSQL_DATABASE: my-db
# MYSQL_ROOT_PASSWORD: password
# MYSQL_USER: admin
# MYSQL_PASSWORD: password
volumes:
# 將 mariadb_data volume 映射到 /var/lib/mysql/
- mariadb_data:/var/lib/mysql/
networks:
- my-dns-network
phpmyadmin:
image: phpmyadmin/phpmyadmin:fpm-alpine
container_name: c_phpmyadmin
stdin_open: true
tty: true
restart: always
environment:
# 當設置為 1 連接到任何伺服器時將被允許(phpmyadmin 頁面伺服器欄位為 Mariadb container names)
- PMA_ARBITRARY=1
# 運行 Mariadb 的主機名或 IP
- PMA_HOST=mariadb
# 運行 Mariadb 的 Port
- PMA_PORT=3306
# Nginx 反向代理(避免 phpMyAdmin 登入、登出網址無 pma/,直接顯示 404 如 pma/ 要修改其它名稱時,也得修改 Nginx config 設定檔中的 location)
- PMA_ABSOLUTE_URI=https://my-dns.com/pma/
volumes:
# 將 phpmyadmin_data volume 映射到 /var/www/html/
- phpmyadmin_data:/var/www/html/
# 新增暗色主題介面
- ${PWD}/docker/phpmyadmin/themes/darkwolf:/var/www/html/themes/darkwolf
depends_on:
- mariadb
networks:
- my-dns-network
nginx:
image: nginx:alpine
container_name: c_nginx
stdin_open: true
tty: true
restart: always
ports:
- "80:80"
# SSL
- "443:443"
volumes:
# Nginx config 自定義設定檔
# - ${PWD}/docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ${PWD}/docker/nginx/nginx.ssl.conf:/etc/nginx/conf.d/default.conf:ro
# 將 phpmyadmin_data volume 映射到給 Nginx 使用
- phpmyadmin_data:/var/www/html/:ro
# 將新增暗色主題介面映射到給 Nginx 使用
- ${PWD}/docker/phpmyadmin/themes/darkwolf:/var/www/html/themes/darkwolf:ro
# SSL 憑證
- ${PWD}/docker/nginx/ssl.crt:/etc/nginx/ssl.crt
# SSL 金鑰
- ${PWD}/docker/nginx/ssl.key:/etc/nginx/ssl.key
depends_on:
- nuxtjs
- mariadb
- phpmyadmin
networks:
- my-dns-network