Docker 入門(二):部署篇
部署篇開頭以兩個簡單的例子快速入門,然後介紹 Dockerfile 的常用命令
簡單的例子
以下使用兩個例子快速入題
官網的例子
這是來自 Docker 官方文件的例子,例子中使用了 Python,但不需要 Python 知識
使用 Dockerfile
生成容器
Docker 使用 Dockerfile
來生成容器。Dockerfile 會自動裝配所用到的環境,所以你唯一需要做的就是敲幾行命令。
Dockerfile
在任意資料夾下建立一個 Dockerfile
,把下面的程式碼複製進去。
# 使用 Python 官方執行環境作為一個父映象
FROM python:2.7-slim
# 將工作目錄設定為 /app
WORKDIR /app
# 把當前目錄下的內容複製到位於 /app 下的容器中
ADD . /app
# 安裝所有在 requirements.txt 中列出的所需要的包
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 向外界開放使容器的 80 埠
EXPOSE 80
# 定義環境變數
ENV NAME World
# 容器裝配好之後執行
CMD ["python", "app.py"]
上面的 Dockerfile 需要 app.py
requirements.txt
兩個檔案,我們繼續建立
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
現在執行下面的命令,生成一個映象,-t
引數後的是映象名,最後的 .
表示當路徑
docker build -t friendlyhello .
使用以下命令檢視所有映象,命令 docker images
與其作用相同
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
☪使用 Linux 的同學可能會遇到網路的問題
以下是官網文件的簡單的翻譯。博主不精通此問題,如有其他需要,請自行百度、Bing、Google…
DNS設定
如果使用了代理伺服器,需要使用ENV
命令開啟 host 的 port
ENV http_proxy host:port ENV https_proxy host:port
代理伺服器設定
DNS 的錯誤配置會導致pip
的問題,可以使用自己的 DNS 伺服器地址使pip
正常工作。通過編輯/etc/docker/daemon.json
,像下面這樣
{"dns": ["your_dns_address", "8.8.8.8"]}
RUN
使用以下命令來執行剛才建立好的映象,-d
引數使其在後臺執行,-p
引數使容器的 80 埠對映到主機的 4000 埠
docker run -d -p 4000:80 friendlyhello
訪問 4000 埠 localhost:4000
,如果 Docker 在其他伺服器上,將 localhost 改為伺服器 IP 即可。如果之前的一切順利,你應該會看到久違的 “Hello World”
然後,使用以下的命令可以檢視所有正在執行的容器。命令 docker ps
與其作用相同
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
書上的例子
這是周立所著 《Spring Cloud與Docker 微服務架構實戰》一書中的例子。從篇幅就看到,這個例子更加簡單一點
使用 Dockerfile
建立容器
和上面例子相同,首先建立一個 Dockerfile
FROM nginx
RUN echo '<h1> Hello World!</h1>' > /usr/share/nginx/html/index.html
在 Dockerfile
所在路徑執行以下構建映象的命令, :
為新映象的標籤, .
表示當前路徑
docker build -t nginx:my .
新增標籤頁可由單獨的命令 docker tag image name:tag
完成。以上面的例子為例:docker tag friendlyhello jackson:v_1
執行
執行啟動 Docker 容器的命令
docker run -d -p 92:80 nginx:my
訪問宿主機 92 埠,例如 123.206.98.122:92
,可以看到 “Hello World”
Dockerfile 常用命令
上面兩個例子中用到了 FROM
,RUN
等命令,事實上,Dockerfile 有十多條指令。指令的一般格式為:指令名稱 引數
ADD
複製檔案ADD <src> ... <dest>
ADD ["<src>",... "dest"]
從
src
目錄複製檔案到容器dest
。src
可以是Dockerfile
所在目錄的相對路徑,也可以是一個URL
,還可以是一個壓縮包注意:
- src 必須在構建的上下文中,不能使用例如:ADD ../something/something/ 這樣的命令
dest
不以/
結尾視作檔案,否則視作目錄src
如果是URL
,其對應內容將被下載到dest
,若src
是一個目錄,整個目錄下的內容都將被複制。如果檔案是可識別的壓縮包,則docker
將會自動解壓
示例:
ADD hello.jar app.jar
ARG
設定構建引數ARG
指令用於設定構建引數,類似於ENV
。和ENV
不同的是,ARG
設定的是構建時的環境變數,在容器執行時是不會存在這些變數的。示例:
ARG use1=someuser
CMD
啟動容器每個
Dockerfile
只有一個CMD
命令,如果指定了多個CMD
,則執行最後一條。有 3 種格式CMD ["executable","param1","param2"]
(推薦)CMD ["param1","param2"]
(為 ENTRYPOINT 指令提供預設引數)CMD command param1 param2
(在 Shell 中執行)
示例:
CMD echo "This is a test." | wc -
COPY
複製檔案ADD <src> ... <dest>
ADD ["<src>",... "dest"]
複製
src
到容器的dest
,和ADD
命令類似。不同的是COPY
指令不支援URL
和壓縮包ENTRYPOINT
入口點ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT
和CMD
指令目的相同ENV
設定環境變數ENV <key> <value>
ENV <key>=<value> ...
示例:
ENV JAVA_HOME /path/to/java
EXPOSE
宣告暴露的埠EXPOSE
宣告用於宣告在執行時容器提供服務的埠,格式為 :EXPOSE <port> [<port>...]
這只是一個宣告,執行時並不會因為一個宣告開啟埠。該指令的作用主要是幫助映象使用者理解該映象服務的守護埠;其次是當執行時使用隨機對映時,會自動對映
EXPOSE
的埠。示例:
# 宣告暴露一個埠示例 EXPOSE port1 # 相應的執行容器使用的命令 docker run -p port1 image # 也可以使用 -P 選項啟動 docker run -P image # 宣告暴露多個埠示例 EXPOSE port1 port2 # 相應的執行容器使用的命令 docker run -p port1 -p port2 image # 也可以指定需要對映到宿主機上的埠號 docker run -p host_port1:port1 -p host_port2:port2 image
FROM
指定基礎映象使用
FROM
指定基礎映象,有點像Java
中的extends
關鍵字。FROM
指令必須指定且要在其他指令之前。FROM
指令過後的所有指令都依賴於該指令所指定的映象。支援 3 種格式:FROM <image>
FROM <image>:<tag>
FROM <image>@<digeset>
LABEL
為映象新增元資料格式為:
LABEL <key>=<value> <key>=<value>...
使用
\
換行。示例:LABEL version="1.0" LABEL description="This is a \ test text"
MAINTAINER
指定維護者的資訊這個指令用於為
Dockerfile
署名示例:
MAINTAINER Cloudy<itsclody.gitee.io/blog>
RUN
執行命令RUN <command>
RUN ["executable","param1","param2"]
RUN <command>
在 shell 終端中執行,在 Linux 中預設是/bin/sh -c
,在 Windows 中是cmd /s /c
,使用這種格式,就像直接在命令列中輸入命令一樣。RUN ["executable","param1","param2"]
使用 exec 執行,這種方式類似於函式呼叫。指定其他終端可以通過該方式操作,例如:RUN ["/bin/bash","-c","echo hello"]
,該方式必須使用雙引號"
,而不能使用'
,因為該方式會被轉換成一個 JSON 陣列USER
設定使用者這個指令設定啟動映象時的使用者或
UID,寫在該指令後的
RUN
、CMD
以及ENTRYPOINT
指令都將使用該使用者執行命令示例:
USER daemon
VOLUME
指定掛載點這個指令使容器中的一個目錄具有持久化儲存的功能,該目錄可被容器本身使用,也可共享給其他容器。當容器中的應用有持久化資料的需求時可以在 Dockerfile 中使用該指令。格式為:
VOLUME ["/data"]
示例:
VOLUME /data
WORKDIR
指定工作目錄格式為:
WORKDIR /path/to/workdir
寫在該命令之後的
RUN
、CMD
以及ENTRYPOINT
指令都將該目錄作為當前目錄,並執行響應的操作其他
其他命令並不常用,不在贅述。有興趣請前往官網文件擴充套件。
後記
翻譯自 Docker 官方文件
借鑑《Spring Cloud與Docker微服務架構實戰》/周立 著