1. 程式人生 > >Docker 入門(二):部署篇

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”

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”

Hello world

Dockerfile 常用命令

上面兩個例子中用到了 FROMRUN 等命令,事實上,Dockerfile 有十多條指令。指令的一般格式為:指令名稱 引數

  1. ADD 複製檔案

    • ADD <src> ... <dest>
    • ADD ["<src>",... "dest"]

    src 目錄複製檔案到容器 destsrc 可以是 Dockerfile 所在目錄的相對路徑,也可以是一個 URL,還可以是一個壓縮包

    注意

    • src 必須在構建的上下文中,不能使用例如:ADD ../something/something/ 這樣的命令
    • dest 不以 / 結尾視作檔案,否則視作目錄
    • src 如果是 URL,其對應內容將被下載到 dest ,若 src 是一個目錄,整個目錄下的內容都將被複制。如果檔案是可識別的壓縮包,則 docker 將會自動解壓

    示例:

    ADD hello.jar app.jar
  2. ARG 設定構建引數

    ARG 指令用於設定構建引數,類似於 ENV。和 ENV 不同的是, ARG 設定的是構建時的環境變數,在容器執行時是不會存在這些變數的。

    示例:

    ARG use1=someuser
  3. 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 -
  4. COPY 複製檔案

    • ADD <src> ... <dest>
    • ADD ["<src>",... "dest"]

    複製 src 到容器的 dest ,和 ADD 命令類似。不同的是 COPY 指令不支援 URL 和壓縮包

  5. ENTRYPOINT 入口點

    • ENTRYPOINT ["executable","param1","param2"]
    • ENTRYPOINT command param1 param2

    ENTRYPOINTCMD 指令目的相同

  6. ENV 設定環境變數

    • ENV <key> <value>
    • ENV <key>=<value> ...

    示例:

    ENV JAVA_HOME /path/to/java
  7. 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
  8. FROM 指定基礎映象

    使用 FROM 指定基礎映象,有點像 Java 中的 extends 關鍵字。FROM 指令必須指定且要在其他指令之前。FROM 指令過後的所有指令都依賴於該指令所指定的映象。支援 3 種格式:

    • FROM <image>
    • FROM <image>:<tag>
    • FROM <image>@<digeset>
  9. LABEL 為映象新增元資料

    格式為:LABEL <key>=<value> <key>=<value>...

    使用 \ 換行。示例:

    LABEL version="1.0"
    LABEL description="This is a \
    test text"
  10. MAINTAINER 指定維護者的資訊

    這個指令用於為 Dockerfile 署名

    示例:

    MAINTAINER Cloudy<itsclody.gitee.io/blog>
  11. 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 陣列

  12. USER 設定使用者

    這個指令設定啟動映象時的使用者或 UID,寫在該指令後的 RUNCMD 以及 ENTRYPOINT 指令都將使用該使用者執行命令

    示例:

    USER daemon
  13. VOLUME 指定掛載點

    這個指令使容器中的一個目錄具有持久化儲存的功能,該目錄可被容器本身使用,也可共享給其他容器。當容器中的應用有持久化資料的需求時可以在 Dockerfile 中使用該指令。格式為: VOLUME ["/data"]

    示例:

    VOLUME /data
  14. WORKDIR 指定工作目錄

    格式為:WORKDIR /path/to/workdir

    寫在該命令之後的 RUNCMD 以及 ENTRYPOINT 指令都將該目錄作為當前目錄,並執行響應的操作

  15. 其他

    其他命令並不常用,不在贅述。有興趣請前往官網文件擴充套件。

後記

翻譯自 Docker 官方文件

借鑑《Spring Cloud與Docker微服務架構實戰》/周立