Deploying Your First Docker Container
Running A Container
- 建一個redis容器
- Find existed image at DockerHub,
docker search <name> - 載入一個image,
docker run <options> <image-name>: 背景執行-d: 預設會執行latest,若要指定版本<image-name>:<version>
docker search redis
docker run -d redis:3.2
Finding Running Containers
- 查看正在跑的container,
docker ps - 看詳細狀態,
docker inspect <friendly-name|container-id> - 看log,
docker logs <friendly-name|container-id>
Accessing Redis
- 為container取一個名字
- 開放port mapping
-p <host-port>:<container-port>
docker run -d --name redisHostPort -p 6379:6379 redis:latest
上述的port mapping是1-1 mapping,當container變多了,就會port conflict。最好的辦法是讓docker自己決定要把map甚麼port,因此只需要告訴container打開6379,讓docker去管理。
docker run -d --name redisDynamic -p 6379 redis:latest
docker port redisDynamic 6379
透過docker port可以知道該container被mapping到哪個port
0.0.0.0:32768
也可以透過docker ps看更進步的訊息,例如ip mapping。
Persisting Data
除了port mapping之外,實體檔案/目錄的mapping也是一個很重要的功能,在docker可以透過-v <host-dir>:<container-dir>來達成。
docker run -d --name redisMapped -v /opt/docker/data/redis:/data redis
除此之外,還可以賦予mapping的目錄存取權限,例如:redis使用的data其他container只能讀取ro。若是進行刪除,就會回報Read-only file system。
docker run -d -v /opt/docker/data/redis:/data:ro ubuntu rm -rf /data
Running A Container In The Foreground
如果不加-d就可以使container在前景執行,若是需要跟container有交互則需要-it,例如使用bash的時候。
docker run ubuntu ps
docker run -it ubuntu bash
container一次只會運行一個application,換句話說,前景執行就是執行完一次,這個container就結束了。bash模式也是同樣的,當用exit退出時container就結束了。
Deploy Application as Container
在本章將要透過nginx來架設一個靜態網頁伺服器。
Create Dockerfile
基本上,透過docker run我們已經有一個可以執行的image,但實際上這個image要能夠正常工作,可能會需要些額外的環境設置,這時候寫一個Dockerfile來告訴image該如何部屬執行環境。
FROM nginx:alpine
COPY . /usr/share/nginx/html
FROM定義了要使用甚麼imageCOPY是container將檔案複製到指定位置EXPOSE <port>, e.g.,EXPOSE 80 443orEXPOSE 7000-8000:EXPOSE只有描述的用途,事實上要真的做到開port還是得要-pRUN <command>CMD ["cmd", "-a", "arga value", "-b", "argb-value"], 用array給要執行的command和參數ENTRYPOINTRUN、CMD、ENTRYPOINT這三個我還沒辦法分清楚它們的使用場合
WORKDIR <dir>, 設定container的工作目錄ADD <dir> <c-dir>, 將某個目錄映射到container內的指定位置
當這些關鍵字前面加了一個ONBUILD的修飾詞,那這些關鍵字就可以被之後引用這個base image的Dockerfile直接套用,例如:
FROM apache:1-onbuild
EXPOSE 8080
假設apache:1-onbuild這個base image已經把環境都設定好了,只差port還沒決定要開在哪,那麼引用的Dockerfile只需要指定port就好,其他事情都由base image包辦。
Build Docker Image
利用docker build引用Dockerfile,指令格式docker build -t <friendly-name>:<version-tag> <build-directory>,可以透過-t給一個名字和打一個tag以標註版本。
docker build -t webserver-image:v1 .
這樣就將一個base image加工成我們自己的,可以根據這個加工的image來長container。另外,可以透過docker images查看在host OS上建立了甚麼image。
Run
當image已經建立完成,就可以透過docker run把container帶起來。
docker run -d -p 80:80 webserver-image:v1
這麼一來就有一個web server在背景執行並且把80 port給開出來。
若是要設定環境變數,可以透過-e ENV=env,如此container帶起來時,就會有指定的環境變數。
Ignore file
若是在使用ADD時有一些想要跳過的檔案,可以建立一個.dockerignore,然後將想要排除的檔案放進去,類似.gitignore。例如:echo privatekey.pem >> .dockerignore。但有些場合是真的需要那把private key,這時候建議透過RUN把用完的檔案給刪掉。
Execute commands
在之前介紹了帶起container時可以選擇要前景執行並且執行command,或者進入bash交互模式來下指令。當container在背景執行時,還是可以在host OS對container操作,這時要透過docker exec,或者pipe模式的docker exec -i。
docker run -d --name r2 redis
docker exec r2 ps aux
echo 'ps aux' | docker exec -i r2 bash
Logging
Docker提供了內建的機制能夠將container內的stdout和stderr倒入檔案,讓使用者可以在host OS透過docker logs查看;或者將輸出導入syslog;也可以直接將所有的輸出關閉。
docker run -d --name r2 redis
docker logs r2
docker run -d --name redis-syslog --log-driver=syslog redis
docker run -d --name redis-none --log-driver=none redis
要查看container使用哪個log driver則可以透過docker inspect查看,有一個簡單的參數可以直接把log driver調出來。
docker inspect --format '{{ .HostConfig.LogConfig }}' r2
Ensuring Uptime
當container因為某些原因掛掉了,這個container就會離開執行狀態,但依然存在,透過docker ps -a還是可以察覺它的存在。Docker可以設定restart policy,--restart,當container內的application結束,會被自動重帶。想要無論甚麼原因都重帶可以設為always,只有在回傳值為非0結束時才重帶則是on-failure。這些策略後面還可以加入重帶次數,例如on-failure:3,就是最多重帶3次。
docker run -d --name restart-always --restart=always scrapbook/docker-restart-example
docker run -d --name restart-always --restart=on-failure scrapbook/docker-restart-example
Docker Stats
Docker提供一套簡易的工具,類似top,稱為docker stats,可以即時監控每個執行的container狀態,例如CPU/memory用量。
docker stats r2
docker ps -q | xargs docker stats
透過docker ps -q列出所有執行中的container的ID,然後丟入docker stats中,因為docker stats讀取的是stdin所以必須使用xargs。
Data Containers
每一個container建立時都是從全新的base image做出來,若是container本身想要保存自身的狀態,那就必須透過data container。據我的理解,data container可以說是一個當作volume的存在,它不實際執行,所以在docker ps看不到它的存在,但其餘執行的container可以儲存資料在它內部,或者利用它來當作載具。
Create Container
要產生一個data container要透過-v <dir>來指定開在container內部的路徑。若是要將現有的檔案放入,可以透過docker cp,就可以將host OS的檔案放入container內部。
docker create -v /config --name dataContainer busybox
docker cp config.conf dataContainer:/config/
Mount Volumes From
當data container已經準備好,就可以將它當作volume給其他的container掛載:
docker run --volumes-from dataContainer ubuntu ls /config
有掛載volume的container就可以直接看到原先就存在內部的檔案,當然也可以將新的檔案放入,新放進去的檔案不會因為container結束執行就消失,下次掛載時依然可以看到。
Export / Import Containers
之所以要用data container來保存檔案而不是採用映射本地目錄的原因在於,若是將檔案放進container內部,那麼就可以用docker export的方式將container匯出,並且搬移到另外一台機器上使用,這樣container的狀態不會被host OS綁住,而是可以被移轉。另外一台機器透過docker import的方式就可以導入。
docker export dataContainer > dataContainer.tar
docker import dataContainer.tar
導入的container具有和匯出的container一樣的狀態:
$ docker import dataContainer.tar
sha256:eca83b8f5f5c05c0e69b6810e0fbb7e9119f5b41860d0f4d2a306d311efed0d0
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> eca83b8f5f5c 14 seconds ago 1.13MB
busybox latest 6ad733544a63 2 months ago 1.13MB