顯示具有 container 標籤的文章。 顯示所有文章
顯示具有 container 標籤的文章。 顯示所有文章

2025年2月17日 星期一

Docker 開發筆記 - 使用 aws cli 和 Docker Exec 進入 AWS ECS Container @ macOS

這個議題比我想像中麻煩了點,讓我回憶起 2009 年寫的 AWS 筆記,那時同事一開始還只在用 Firefox extension 管理 AWS EC2 呢 XD 我覺得這理論上要能都透過網頁搞定才對,先把目前研究的過程筆記一下。

總之,要能像 ssh 遠端(docker exec -it ContainerID bash)進去 AWS ECS container 的關鍵之處:
  • 使用 awscli 做事
  • AWS ECS 的 Task 定義,基礎設施需求 -> 任務角色,需要指定一下角色,例如 ecsTaskExecutionRole
  • AWS IAM -> ecsTaskExecutionRole -> 添加 AmazonSSMManagedInstanceCore 權限
  • AWS ECS -> Cluster -> Service ,需要用 awscli 啟動 enable-execute-command ,並且重新更新服務,使之生效
  • 使用 aws 指令登入
首先,先下載 awscli 並且版本要夠新:
安裝後檢查版本,版本太低會無法完成任務:

% aws --version
aws-cli/2.24.5 Python/3.12.6 Darwin/24.3.0 exe/x86_64

接著還要安裝 Session Manager plugin,此例紀錄 Mac with Apple silicon 版:
% curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac_arm64/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
% unzip sessionmanager-bundle.zip
% sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin

基本的環境已準備好了,下一刻是查看自己的 AWS ECS 的任務定義是否有把 任務角色 設定好,這部就維持用網頁吧:



若你的 AWS ECS 上定義的 Task 只有一個,也可以偷懶靠 awscli 操作(在此就不贅述 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION 部分),會用到的指令:

aws ecs list-task-definition-families --status ACTIVE
aws ecs list-task-definitions --family-prefix webapp
aws ecs describe-task-definition --task-definition webapp:3

連續技,快速檢查 taskRoleArn 跟 executionRoleArn:

% NamespaceID=$(aws ecs list-task-definition-families --status ACTIVE | jq -r '.families[0]') ; echo "Namespace: $NamespaceID" ; TaskID=$(aws ecs list-task-definitions --family-prefix "$NamespaceID" | jq -r '.taskDefinitionArns[0]') ; echo "Task: $TaskID" ; aws ecs describe-task-definition --task-definition "$TaskID" | jq ".taskDefinition | { taskRoleArn: .taskRoleArn, executionRoleArn: .executionRoleArn}"
Namespace: myapp-task
Task: arn:aws:ecs:ap-northeast-1:####:task-definition/myapp-task:2
{
  "taskRoleArn": "arn:aws:iam::####:role/ecsTaskExecutionRole",
  "executionRoleArn": "arn:aws:iam::####:role/ecsTaskExecutionRole"
}

接下來,若 AWS ECS Cluster 還沒有建立任何 Service,用指令查:

% aws ecs list-tasks --cluster myapp-cluster  
{
    "taskArns": []
}

接著我們在 AWS ECS 網頁端起了一個 Service 名為 myapp-service ,在創建過程中沒看到啟用 enable-execute-command,這時在網頁上查看也是顯示 "ECS 執行: 關閉"



接下來用 aws cli 查詢:

% aws ecs list-tasks --cluster myapp-cluster   
{
    "taskArns": [
        "arn:aws:ecs:ap-northeast-1:####:task/myapp-cluster/#TASKID#"
    ]
}

% TaskID=$(aws ecs list-tasks --cluster myapp-cluster | jq -r '.taskArns[0]') ; echo "TaskID: $TaskID" ; aws ecs describe-tasks --cluster myapp-cluster --tasks $TaskID | jq '.tasks[0] | { "clusterArn": .clusterArn, "taskArn": .taskArn, "taskDefinitionArn": .taskDefinitionArn, "group": .group, "healthStatus": .healthStatus, "desiredStatus": .desiredStatus, "enableExecuteCommand": .enableExecuteCommand, "containers-name": [.containers |.[] | { "name":.name, "runtimeId": .runtimeId} ] }'
TaskID: arn:aws:ecs:ap-northeast-1:####:task/myapp-cluster/#TASKID#
{
  "clusterArn": "arn:aws:ecs:ap-northeast-1:####:cluster/myapp-cluster",
  "taskArn": "arn:aws:ecs:ap-northeast-1:####:task/myapp-cluster/#TASKID#",
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:####:task-definition/myapp-task:2",
  "group": "service:myapp-service",
  "healthStatus": "HEALTHY",
  "desiredStatus": "RUNNING",
  "enableExecuteCommand": false,
  "containers-name": [
    {
      "name": "php-fpm-docker",
      "runtimeId": "#TASKID#-#ContainerID#"
    },
    {
      "name": "web-docker",
      "runtimeId": "#TASKID#-#ContainerID#"
    }
  ]
}

可以看到 enableExecuteCommand 為 false

這時候,如果透過 aws cli 來設法登入到 Container:

% aws ecs execute-command --cluster myapp-cluster --task #TASKID# --container #containers#name# --command "/bin/bash" --interactive


The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


An error occurred (InvalidParameterException) when calling the ExecuteCommand operation: Unable to start session because the container doesn’t exist. Specify a valid container and try again.

接著,使用 aws cli 來啟動 enableExecuteCommand 吧:

% aws ecs update-service --cluster myapp-cluster --service arn:aws:ecs:ap-northeast-1:####:service/myapp-cluster/myapp-service --enable-execute-command 
{
    "service": {
        ... 
        "enableExecuteCommand": true,
        ...
    }
}

可以看到 enableExecuteCommand 被標記成 true 了,這時還需要重新發布服務,可以重網頁去觸發,或是靠指令觸發:

% aws ecs update-service --cluster myapp-cluster --service arn:aws:ecs:ap-northeast-1:####:service/myapp-cluster/myapp-service --force-new-deployment

當服務發布完畢後,在網頁上就可以看到改變,或是用指令在查一次:

% TaskID=$(aws ecs list-tasks --cluster myapp-cluster | jq -r '.taskArns[0]') ; echo "TaskID: $TaskID" ; aws ecs describe-tasks --cluster myapp-cluster --tasks $TaskID | jq '.tasks[0] | { "clusterArn": .clusterArn, "taskArn": .taskArn, "taskDefinitionArn": .taskDefinitionArn, "group": .group, "healthStatus": .healthStatus, "desiredStatus": .desiredStatus, "enableExecuteCommand": .enableExecuteCommand, "containers-name": [.containers |.[] | { "name":.name, "runtimeId": .runtimeId} ] }'
TaskID: arn:aws:ecs:ap-northeast-1:####:task/myapp-cluster/#TASKID#
{
  "clusterArn": "arn:aws:ecs:ap-northeast-1:####:cluster/myapp-cluster",
  "taskArn": "arn:aws:ecs:ap-northeast-1:####:task/myapp-cluster/#TASKID#",
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:####:task-definition/myapp-task:2",
  "group": "service:myapp-service",
  "healthStatus": "HEALTHY",
  "desiredStatus": "RUNNING",
  "enableExecuteCommand": true,
  "containers-name": [
    {
      "name": "php-fpm-docker",
      "runtimeId": "#TASKID#-#CONTAINERID#"
    },
    {
      "name": "web-docker",
      "runtimeId": "#TASKID#-#CONTAINERID#"
    }
  ]
}

如此,就可以正式遠端進去一下:

% aws ecs execute-command --cluster myapp-cluster --task #TASKID# --container web-docker --command "/bin/bash" --interactive

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-################
ip-123-45-6-123:/var/www/html# 

收工

參考資料:

2025年2月16日 星期日

Docker 開發筆記 - AWS ECS 發布 Docker Container 服務和 Gitlab CI/CD 架構實踐


上回在 Docker 開發筆記 - 從 Gitlab 觸發 CI/CD,製作 Docker Image 並發布到 Amazon Elastic Container Service (AWS ECS) 已經提到在 Gitlab.com 完成 Docker Images 的建置、打包、儲存至 Gitlab Container Registry 的架構,以及從 AWS ECS 上如何取得 Gitlab Container Registry 的資料,但沒有紀錄太多 AWS ECS 筆記,這次就完整順一次在 AWS ECS 發布服務時要經歷的事情。我們挑 AWS Japan Region (ap-northeast-1) 來做事。

第一步,可以先在 AWS ECS 建立 Task,例如取名為 myapp-task,過程中會設置 "基礎設施需求" 和 數個 "容器" 設定。




在 基礎設施需求 頁面,有幾個重點要留意:
  • 啟動類型是 AWS Fargate 還是 Amazon EC2 
  • 網路類型
  • 作業系統/架構,CPU, 記憶體
  • 任務角色,是否有從 Container 內發送 AWS API 的需求,以及執行 Container 建置時,要用哪個角色(預設為 ecsTaskExecutionRole)
此例先以 AWS Fargate, Linux/X86_64, 1 vCPU, 2GB 為例。

接下來定義容器的部分,此例會定義兩個容器,一個是 web container ,一個以 nginx 為基礎的 Docker Image,另一個是 app container,一個是 php-fpm 為基礎的 Docker Image

容器 - 1,一個單純的 Laravel framework project

- 名稱: php-fpm-docker
- 映像 URI: registry.gitlab.com/MyGroup/MyProject/myapp-php-fpm:latest
- 基本容器: 是
- 私有登入檔案: On
- Secrets Manager ARN 或名稱: arn:aws:secretsmanager:ap-northeast-1:####:secret:gitlab.com-container-registry
- 連接映射
  - 容器連接 9000, 通訊協定 TCP, 連接阜名稱 9000, 應用程式通訊協定 HTTP
- 唯讀根檔案系統, 唯讀: 否
- CPU: 0.5
- 記憶體硬性限制: 1.5GB, 記憶體軟性限制: 1.5GB
- 環境變數
  - PHPFPM_HOST, localhost
  - PHPFPM_PORT, 9000
- 運作狀態檢查: CMD-SHELL,/usr/local/bin/healthcheck.sh

 

 

容器 - 2,一個單純的 nginx web server

- 名稱: web-docker
- 映像 URI: registry.gitlab.com/MyGroup/MyProject/myapp-nginx:latest
- 基本容器: 是
- 私有登入檔案: On
- Secrets Manager ARN 或名稱: arn:aws:secretsmanager:ap-northeast-1:####:secret:gitlab.com-container-registry
- 連接映射
  - 容器連接 80, 通訊協定 TCP, 連接阜名稱 80, 應用程式通訊協定 HTTP
- 唯讀根檔案系統, 唯讀: 否
- CPU: 0.5
- 記憶體硬性限制: 0.5GB, 記憶體軟性限制: 0.5GB
- 環境變數
  - PHPFPM_HOST, localhost
  - PHPFPM_PORT, 9000
- 運作狀態檢查: CMD-SHELL,/usr/local/bin/healthcheck.sh
- 啟動相依性排序: php-fpm-docker, 條件: Healthy


其中的 私有登入檔案 就是用來存取 registry.gitlab.com Container Registry 的地方,請記得在 Gitlab.com Project 建立 Deploy token 得到一組帳密:



接著到 AWS Secrets Manager 添加一組,在此定為 gitlab.com-container-registry 名稱:

https://ap-northeast-1.console.aws.amazon.com/secretsmanager/listsecrets?region=ap-northeast-1



添加完得到 arn:aws:secretsmanager:ap-northeast-1:####:secret:gitlab.com-container-registry。

下一刻,到 AWS IAM Roles 設定,讓 ecsTaskExecutionRole 可以讀取 secretsmanager 內的資料:

https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles



在此透過自訂一個足夠大的權限即可,例如可讀必要的資料即可(建議限制 Resource 可以存取地區甚至命名規則等):


如此,終於把 AWS ECS - Task 運行時所要的設定都安置好了,下一刻就是回到 AWS ECS - Cluster,建立一個 myapp-cluster,其中基礎設施維持使用 AWS Fargate (無伺服器) 模式,接著來建立 Service ,建立 AWS ECS -> Cluster -> Service 時,就比較多要留意的地方



  • 環境
    • 運算組態: 都用預設的,需看一眼確認運算選項: 容量供應商策略
  • 部署組態: 
    • 應用程式類型: 服務
    • 任務定義: myapp-task (也就是剛剛創立的 myapp,內有定義兩個容器)
    • 服務名稱: myapp-service
  • 聯網: 
    • VPC, 子網路: 需要留意, 可自行設計
    • 安全群組: 需要留意, 可自行設計
    • 公有 IP: 開啟
  • Load Balancer
    • 使用負載平衡
    • 負載平衡器類型: Application Load Balancer
    • 容器: web-docker 80:80
    • Application Load Balancer: 建立新的負載平衡器
    • 負載平衡器名稱: myapp-service-load-balanacer
    • 接聽程式: 80, HTTP
    • 目標群組: 建立新的目標群組, 目標群組名稱 ecs-myapp--myapp-service, 通訊協定 HTTP, 取消註冊延遲 300, 運作狀態檢查通訊協定 HTTP, 運作狀態檢查路徑 /



按下建立 myapp-service 後,在 AWS ECS Cluster 頁面上不一定會馬上看到,有時需要重整頁面數次才會看到資訊,接著我們進去 Amazon Elastic Container Service -> 叢集 -> myapp-cluster -> 服務觀看:

https://ap-northeast-1.console.aws.amazon.com/ecs/v2/clusters/myapp-cluster/services?region=ap-northeast-1



再往下點進 myapp-service 進入到運作狀態,如網址 https://ap-northeast-1.console.aws.amazon.com/ecs/v2/clusters/myapp-cluster/services/myapp-service/health?region=ap-northeast-1 等
   
接著也可以點擊 Load Balancer 得知分配到的 DNS name,如 myapp-service-load-balanacer-##########.ap-northeast-1.elb.amazonaws.com 去瀏覽。此外 Load Balancer 這邊也有個小技巧,其實可以讓容器只提供 HTTP 80 服務,單純從 Load Balancer 增加 HTTPS 443 的服務,並把流量導過去 80,這也是讓 Load balancer 幫你扛掉一些算力的架構,但自身的服務也需要一些判斷設定,避免一直無限強制跳轉到 https 等。

如此,就算完成一個服務部署了,練習後想要刪光資源,記得刪掉 Service 後,有用到 Load balancer 的,還要特別去 EC2 Load Balancer 去刪除釋放掉資源,該 Load Balancer 就像一組 EC2 機器,創建多久算多久的錢。

接下來的實驗,就不需依賴 Load Balancer ,可以單純有個 Public IP 可存取即可。刪掉 Service 後,再重新創一個,接著我們要設計 CI/CD 架構,如何通報 AWS ECS 更新服務(Containers),這邊研究一下後,有兩種設計原理:
  1. 不停的去追蹤 registry.gitlab.com/MyGroup/MyProject/myapp-php-fpm:latest 和 registry.gitlab.com/MyGroup/MyProject/myapp-nginx:latest 是否有更新,有更新時透過 aws cli 通報 AWS ECS -> Cluster -> Service -> 觸發更新任務
  2. 在 Gitlab.com 創建 Docker images 時,最後一刻發動 aws cli 通報 AWS ECS -> Cluster -> Service -> 觸發更新任務
其中 (1) 的策略是透過 Amazon EventBridge 去排程執行,原理上需要記錄 Container Registry 的狀態,像是每次執行時,把資料記錄在 DB 內,下次檢查發現有變動時,呼叫 "AWS ECS -> Cluster -> Service -> 觸發更新任務" 後,再把狀態記錄下來,此優點是不用暴露 AWS 的資訊出去,缺點是效率較差,以及需要額外資料紀錄。此例 CI/CD 實踐是用 (2) 招式,建立一個身份可以完成 "AWS ECS -> Cluster -> Service -> 觸發更新任務" 即可。

首先在 IAM 創立一個人員: gitlab.com-call-AWS-ECS-Cluster-Service-Update

https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/users/create


接著建立政策: https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/policies/create



給予以下權限
  • Read: DescribeServices
  • Write: UpdateService
  • Specify ARNs: ap-northeast-1, myapp-cluster
取名為: AWS-ECS-Cluster-Service-Update


如此,後續就可以改到 Gitlab.com 串 CI/CD 了,例如 .gitlab-ci.yml 和 tool/aws/ecs-update-service.sh

deploy_to_ecs:
stage: deploy
image: alpine:latest
needs:
- job: web_docker_image_build
optional: true
- job: app_docker_image_build
optional: true
before_script:
- apk add --no-cache aws-cli curl jq tree bash
- echo "AWS_ACCESS_KEY_ID = ${AWS_ACCESS_KEY_ID}"
- echo "AWS_SECRET_ACCESS_KEY = ${AWS_SECRET_ACCESS_KEY}"
- echo "AWS_DEFAULT_REGION = ${AWS_DEFAULT_REGION}"
- echo "ECS_DEPLOY_ENABLE = ${ECS_DEPLOY_ENABLE}"
- echo "ECS_CLUSTER = ${ECS_CLUSTER}"
- echo "ECS_SERVICE = ${ECS_SERVICE}"
script:
- chmod +x tool/aws/ecs-update-service.sh
- bash tool/aws/ecs-update-service.sh
rules:
- if: $CI_COMMIT_TAG =~ /^web\-v\d+\.\d+\.\d+$/
when: on_success
- if: $CI_COMMIT_TAG =~ /^app\-v\d+\.\d+\.\d+$/
when: on_success
- if: '$CI_PIPELINE_SOURCE == "web"'
when: on_success
- if: '$CI_PIPELINE_SOURCE == "api"'
when: on_success

當創建了相關命名規則的 git tag 後,將觸發 deploy stage 做事,在此規劃 Gitlab.com Project -> Settings -> CI/CD 需要定義相關參數,當參數存在時,就會透過 AWS cli 更新雲端的服務,邏輯上依序呼叫:
  1. aws ecs describe-services --cluster myapp-cluster --services myapp-service | jq '.services | .[] | .events'
  2. aws ecs wait services-stable --cluster myapp-cluster --services myapp-service && echo "Status is stable"
  3. aws ecs update-service --cluster myapp-cluster --service myapp-service --force-new-deployment
  4. aws ecs wait services-stable --cluster myapp-cluster --services myapp-service && echo "Done"

以上就是稍微完整的流程,但仍有很多有趣的地方沒有細說,包括 Docker 的建置、AWS VPC/Security Group/NAT Gateway/ECS Container 啟動類型的影響/Container 狀態檢查該怎樣設計/Zero Downtime/刪除 ECS 服務後仍要手動釋放Load Balancer等,此外,在 Gitlab.com 的 git tag 事件也有滿多有趣的,包括觸發 deploy 跟 build 的 git tag 規則是可以不一樣的,以及在 Gitlab.com 上的 Runner 運行了敏感資料 (aws cli, AWS Access Key ID, AWS Secret Access Key)、是否到底足夠信任挑選的 docker images 等等,都是值得深思的議題。

2014年10月24日 星期五

[Linux] Docker 使用筆記 - 透過 nsenter 進入當前 container 操作環境 @ Ubuntu 14.04

早期的 Docker 可以直接用 lxc-attach 取得 container 的 terminal 環境:

$ sudo docker ps --no-trunc
$ sudo lxc-attach -n CONTAINER_ID


但新版的只會噴 lxc-attach: failed to get the init pid 訊息,所以可以改用 nsenter 來操作吧!

$ sudo docker version
Client version: 1.0.1
Client API version: 1.12
Go version (client): go1.2.1
Git commit (client): 990021a
Server version: 1.0.1
Server API version: 1.12
Go version (server): go1.2.1
Git commit (server): 990021a

$ curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-
$ cd util-linux-2.24
$ ./configure --without-ncurses
$ make nsenter
$ sudo cp nsenter /usr/local/bin

$ sudo docker inspect --format "{{ .State.Pid }}" CONTAINER_ID_OR_NAME
$ sudo nsenter --target $PID --mount --uts --ipc --net --pid
root@##############:/#

2014年8月19日 星期二

[Linux] 初次使用 Docker 筆記 @ Ubuntu 14.04

最近找尋系統監控的方式時,無意間看到 Docker 的消息,雖然以前用過 LXC 一陣子,久了沒用又都忘光光,這次 Docker 還滿紅的,就順手學一下吧!若安裝前,想體驗一下,可以試看看官網推的教學模式:https://www.docker.com/tryit/

在使用前,想說找一下 Docker 的商業模式,找了很久都沒看到 XD 直到使用 Docker hub 時才發現,商業模式就像 github/bitbucket 一樣,想要建立 private repo 的則需要付費,此例就是可以打包自己的開發環境送到 Docker hub 上使用,免費方案有提供 1 個 private 單位哦。


回到筆記,根據官網介紹 https://docs.docker.com/installation/ubuntulinux/,依序幾個動作就完成安裝了:

$ sudo apt-get update
$ sudo apt-get install docker.io
$ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
$ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io


開始使用:

$ sudo docker run ubuntu:12.04 echo "hello world"
Unable to find image 'ubuntu:12.04' locally
Pulling repository ubuntu
822a01ae9a15: Download complete
511136ea3c5a: Download complete
93c381d2c255: Download complete
a5208e800234: Download complete
9fccf650672f: Download complete
1186c90e2e28: Download complete
f6a1afb93adb: Download complete
hello world


此命令是說要跑一個 ubuntu 12.04 環境,在其環境執行 echo "hello world" 的意思,整個過程就是包含初始化(下載image)後,最後在執行 echo "hello world",有興趣可以再執行一次,這次就不會再去下載 image 了。

然而,上述的動作只是一次性的,舉例來說,初始環境執行 apt-get install curl 是會出錯的:

$ sudo docker run ubuntu:12.04 apt-get install curl
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package curl


但只要 apt-get update 後就會正常,但不能分開執行:

$ sudo docker run ubuntu:12.04 apt-get update
Get:1 http://archive.ubuntu.com precise Release.gpg [198 B]
Get:2 http://archive.ubuntu.com precise-updates Release.gpg [198 B]
Get:3 http://archive.ubuntu.com precise-security Release.gpg [198 B]
...
Reading package lists...
$ sudo docker run ubuntu:12.04 apt-get install curl
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package curl


因此,正式的使用其實是開個 terminal 進去連續動作:

$ sudo docker run -t -i ubuntu:12.04
root@431bb00c701d:/#


其中 431bb00c701d 則是此 container ID,

root@431bb00c701d:/# apt-get install wget
Reading package lists... Done
Building dependency tree    
Reading state information... Done
E: Unable to locate package wget
root@431bb00c701d:/# apt-get update
...
root@431bb00c701d:/# apt-get install wget
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following extra packages will be installed:
  libidn11
The following NEW packages will be installed:
  libidn11 wget
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 391 kB of archives.
After this operation, 966 kB of additional disk space will be used.
Do you want to continue [Y/n]?


接著按 exit 離開後,其實就跟上述單行指令操作一樣,什麼都沒留下,因此在離開之前,想要保存環境則是要進行 commit。

此時,必須額外再開一個 terminal 用 docker ps 查看目前已執行的 image 環境:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5db62a9bf492        ubuntu:14.04        /bin/bash           11 seconds ago      Up 10 seconds                           goofy_curie      
431bb00c701d        ubuntu:12.04        /bin/bash           35 seconds ago      Up 34 seconds                           agitated_thompson


此例代表有2個 container 在運行,此例目標是 ubuntu:12.04 的 431bb00c701d ,想要儲存環境變化,就來個 commit 吧

$ sudo docker commit -m 'ubuntu 12.04 with wget' 431bb00c701d
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
<none>              <none>              aac0f5ce2936        9 minutes ago       137.7 MB
ubuntu              14.04               c4ff7513909d        7 days ago          213 MB
ubuntu              12.04               431bb00c701d        7 days ago          108 MB


想要有更佳的描述,就在 docker commit  時,多加一點資訊 REPOSITORY[:TAG] 吧:

$ sudo docker commit -m 'ubuntu 12.04 with wget' e7e35769932d MyUbuntu:12.04
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
MyUbuntu            12.04               d3466dce0e51        About a minute ago   108 MB
<none>              <none>              aac0f5ce2936        10 minutes ago       137.7 MB
ubuntu              14.04               c4ff7513909d        7 days ago           213 MB
ubuntu              12.04               431bb00c701d        7 days ago           108 MB


下次要用時:

$ sudo docker run -i -t MyUbuntu:12.04
root@600d3fee924d:/# wget
wget: missing URL
Usage: wget [OPTION]... [URL]...

Try `wget --help' for more options.


@ 2014-10-24 加映場:[Linux] Docker 使用筆記 - 常用指令 @ Ubuntu 14.04