1. 程式人生 > >Docker實戰(五)編寫Dockerfile

Docker實戰(五)編寫Dockerfile

curl 進行 () hostname 添加文件 iso -name 默認 數據卷

一、創建Dockerfile文件

首先,需要創建一個目錄來存放 Dockerfile 文件,目錄名稱可以任意,在目錄裏創建Dockerfile文件:

技術分享圖片

二、Dockerfile 基本框架

Dockerfile一般包含下面幾個部分:

  1. 基礎鏡像:以哪個鏡像作為基礎進行制作,用法是FROM 基礎鏡像名稱
  2. 維護者信息:需要寫下該Dockerfile編寫人的姓名或郵箱,用法是MANITAINER 名字/郵箱
  3. 鏡像操作命令:對基礎鏡像要進行的改造命令,比如安裝新的軟件,進行哪些特殊配置等,常見的是RUN 命令
  4. 容器啟動命令:當基於該鏡像的容器啟動時需要執行哪些命令,常見的是CMD 命令ENTRYPOINT

在本節實驗中,我們依次先把這四項信息填入文檔。Dockerfile中的#標誌後面為註釋,可以不用寫。

打開Dockerfile,依次輸入下面的基本框架內容:

01 02 03 04 05 06 07 08 09 10 11 12 13 # Version 0.1 # 基礎鏡像 FROM debian:latest # 維護者信息 MAINTAINER [email protected] # 鏡像操作命令 RUN apt-get -yqq update && apt-get install -yqq apache2 && apt-get clean
# 容器啟動命令 CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

上面的Dockerfile非常簡單,創建了一個apache的鏡像。包含了最基本的四項信息。

其中FROM指定基礎鏡像,如果鏡像名稱中沒有制定TAG,默認為latestRUN命令默認使用/bin/sh Shell執行,默認為root權限。如果命令過長需要換行,需要在行末尾加\CMD命令也是默認在/bin/sh中執行,並且默認只能有一條,如果是多條CMD命令則只有最後一條執行。用戶也可以在docker run命令創建容器時指定新的CMD命令來覆蓋Dockerfile裏的CMD

這個Dockerfile已經可以使用docker build創建新鏡像了,先構建一個版本dockertest:0.1:

1 2 # 在dockertest目錄,即Dockerfile所在的目錄執行 docker build -t dockertest:0.1 .

構建需要安裝apache2,會花幾分鐘,最後查看新創建的鏡像:

技術分享圖片

使用該鏡像創建容器site1,將容器中的端口8888映射到本地80端口:

1 docker run -d -p 8888:80 --name site1 dockertest:0.1

使用瀏覽器打開localhost:8888進行測試,查看是否apache已運行:

技術分享圖片

三、Dockerfile 編寫常用命令

在上述基本的架構下,我們根據需求可以增加新的內容到Dockerfile中。後續的擴展操作都需要放置在Dockerfile的鏡像操作部分。

1)指定容器運行的用戶

該用戶將作為後續的RUN命令執行的用戶。命令使用方式,例如使用nginx用戶來執行後續命令:

1 USER nginx

2)指定後續命令的執行目錄

由於我們需要運行的是一個靜態網站,將啟動後的工作目錄切換到/var/www/html目錄:

1 WORKDIR /var/www/html

3)對外連接端口號

由於內部服務會啟動Web服務,我們需要把對應的80端口暴露出來,可以提供給容器間互聯使用,可以使用EXPOSE命令。

在鏡像操作部分增加下面一句:

1 EXPOSE 80

4)設置容器主機名

ENV命令能夠對容器內的環境變量進行設置,我們使用該命令設置由該鏡像創建的容器的主機名為dockertest,向Dockerfile中增加下面一句:

1 ENV HOSTNAME dockertest

5)向鏡像中增加文件

向鏡像中添加文件有兩種命令:COPYADD

COPY命令可以復制本地文件夾到鏡像中:

1 COPY site1 /var/www/html

ADD 命令支持添加本地的tar壓縮包到容器中指定目錄,壓縮包會被自動解壓為目錄,也可以自動下載URL並拷貝到鏡像,例如:

1 2 ADD html.tar /var/www ADD http://192.168.1.200/html.tar /var/www

6)CMD 與 ENTRYPOINT

ENTRYPOINT 容器啟動後執行的命令,讓容器執行表現的像一個可執行程序一樣,與CMD的區別是不可以被docker run覆蓋,會把docker run後面的參數當作傳遞給ENTRYPOINT指令的參數。Dockerfile中只能指定一個ENTRYPOINT,如果指定了很多,只有最後一個有效。docker run命令的-entrypoint參數可以把指定的參數繼續傳遞給ENTRYPOINT

7)掛載數據卷

將apache訪問的日誌數據存儲到宿主機可以訪問的數據卷中:

1 VOLUME ["/var/log/apche2"]

8)設置容器內的環境變量

使用ENV設置一些apache啟動的環境變量:

1 2 3 4 5 6 ENV APACHE_RUN_USER www-data ENV APACHE_RUN_GROUP www-data ENV APACHE_LOG_DIR /var/log/apche2 ENV APACHE_PID_FILE /var/run/apache2.pid ENV APACHE_RUN_DIR /var/run/apache2 ENV APACHE_LOCK_DIR /var/lock/apche2

9)使用 Supervisord

CMD如果只有一個命令,那如果我們需要運行多個服務怎麽辦呢?最好的辦法是分別在不同的容器中運行,通過link進行連接。如果一定要在一個容器中運行多個服務可以考慮用Supervisord來進行進程管理,方式就是將多個啟動命令放入到一個啟動腳本中。

首先安裝Supervisord,添加下面內容到Dockerfile:

1 2 RUN apt-get install -yqq supervisor RUN mkdir -p /var/log/supervisor

拷貝配置文件到指定的目錄:

1 COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

其中supervisord.conf文件需要放在dockertest目錄下,文件內容如下:

1 2 3 4 5 [supervisord] nodaemon=true [program:apache2] command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2ctl -D FOREGROUND"

如果有多個服務需要啟動可以在文件後繼續添加[program:xxx],比如如果有ssh服務,可以增加[program:ssh]

修改CMD命令,啟動Supervisord

1 CMD ["/usr/bin/supervisord"]

四、從 Dockerfile 創建鏡像

在dockertest文件夾中有如下三個文件:

Dockerfile

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # debian apache2 php5 ssh vim # Version 0.2 # 基礎鏡像 FROM debian:latest # 維護者信息 MAINTAINER [email protected] # 設置debian的鏡像,加快速度 RUN echo ‘deb http://mirrors.aliyun.com/debian/ jessie main non-free contrib‘ > /etc/apt/sources.list \ && echo ‘deb http://mirrors.aliyun.com/debian/ jessie-proposed-updates main non-free contrib‘ >> /etc/apt/sources.list \ && echo ‘deb http://mirrors.aliyun.com/debian-security/ jessie/updates main non-free contrib‘ >> /etc/apt/sources.list # 鏡像操作命令 RUN apt-get -yqq update \ && apt-get install -yqq supervisor openssh-server openssh-client vim \ && apt-get install -yqq apache2 php5 php5-mcrypt php5-mysql php5-imagick php5-json php5-curl \ && apt-get clean # 設置 ssh,root密碼為 www.wanglu.info RUN echo ‘root:www.wanglu.info‘ | chpasswd \ && mkdir /var/run/sshd \ && sed -i ‘s/PermitRootLogin without-password/PermitRootLogin yes/‘ /etc/ssh/sshd_config # 設置 supervisor RUN mkdir -p /var/log/supervisor COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf # 拷貝phpinfo.php文件到容器的 /var/www/html COPY phpinfo.php /var/www/html ENV HOSTNAME docker-test ENV APACHE_RUN_USER www-data ENV APACHE_RUN_GROUP www-data ENV APACHE_LOG_DIR /var/log/apache2 ENV APACHE_PID_FILE /var/run/apache2.pid ENV APACHE_RUN_DIR /var/run/apache2 ENV APACHE_LOCK_DIR /var/lock/apache2 EXPOSE 22 80 # 啟動容器命令 CMD ["/usr/bin/supervisord"]

supervisord.conf

1 2 3 4 5 6 7 8 9 # supervisord configuration [supervisord] nodaemon=true [program:ssh] command=/usr/sbin/sshd -D [program:apache] command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2ctl -D FOREGROUND"

phpinfo.php

1 2 <?php phpinfo();

在dockertest目錄下使用 docker build 執行創建,-t參數指定鏡像名稱:

1 docker build -t dockertest:0.2 .

docker images 查看創建的新鏡像已經出現在了鏡像列表中:

技術分享圖片

由該鏡像創建新的容器site2,並映射本地的8080端口到容器的80端口、8022端口到容器的22端口:

1 docker run -d -p 8080:80 -p 8022:22 --name site2 dockertest:0.2

五、運行測試

部分操作截圖:

技術分享圖片

打開測試網頁

技術分享圖片

Docker實戰(五)編寫Dockerfile