【DevOps】第一步: 編寫Dockerfile與項(xiàng)目實(shí)踐

一丘逸、Dockerfile簡介

Dockerfile 是一個文本文件,其內(nèi)包含了一條條的 指令(Instruction)花墩,每一條指令構(gòu)建一層复斥,因此每一條指令的內(nèi)容营密,就是描述該層應(yīng)當(dāng)如何構(gòu)建。

Dockerfile分為四部分:

  • FROM:基礎(chǔ)鏡像信息
  • MAINTAINER:維護(hù)者信息
  • RUN目锭、COPY评汰、ADD、EXPOSE等:鏡像操作指令
  • CMD痢虹、ENTRYPOINT:容器啟動時執(zhí)行指令被去。

例如:

FROM python:3.6

MAINTAINER cbbing <cbbing@163.com>

COPY pip.conf requirements.txt /root/.pip/

#設(shè)置時區(qū)
ENV TZ=Asia/Shanghai
ENV PYTHONPATH=/usr/src/app

RUN mkdir -p /usr/src/app \
    && pip install -r /root/.pip/requirements.txt \
    && apt-get update \
    && apt-get install -y supervisor \
    && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && echo $TZ > /etc/timezone

WORKDIR /usr/src/app

CMD ["python"]

Dockerfile指令

指令的一般格式為 INSTRUCTION arguments,指令包括 FROM奖唯、MAINTAINER惨缆、RUN 等。

1. FROM

格式為 FROM <image>或FROM <image>:<tag>丰捷。
第一條指令必須為 FROM 指令坯墨。并且,如果在同一個Dockerfile中創(chuàng)建多個鏡像時瓢阴,可以使用多個 FROM 指令(每個鏡像一次)畅蹂。

2. MAINTAINER

格式為 MAINTAINER <name>健无,指定維護(hù)者信息荣恐。

3. RUN

格式為 RUN <command> 或 RUN ["executable", "param1", "param2"]。
前者將在 shell 終端中運(yùn)行命令累贤,即 /bin/sh -c叠穆;后者則使用 exec 執(zhí)行。指定使用其它終端可以通過第二種方式實(shí)現(xiàn)臼膏,例如 RUN ["/bin/bash", "-c", "echo hello"]硼被。
每條 RUN 指令將在當(dāng)前鏡像基礎(chǔ)上執(zhí)行指定命令,并提交為新的鏡像渗磅。當(dāng)命令較長時可以使用 \ 來換行嚷硫。

4. CMD

支持三種格式
CMD ["executable","param1","param2"] 使用 exec 執(zhí)行检访,推薦方式;
CMD command param1 param2 在 /bin/sh 中執(zhí)行仔掸,提供給需要交互的應(yīng)用脆贵;
CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認(rèn)參數(shù);
指定啟動容器時執(zhí)行的命令起暮,每個 Dockerfile 只能有一條 CMD 命令卖氨。如果指定了多條命令,只有最后一條會被執(zhí)行负懦。
如果用戶啟動容器時候指定了運(yùn)行的命令筒捺,則會覆蓋掉 CMD 指定的命令。

5. EXPOSE

格式為 EXPOSE <port> [<port>...]纸厉。
告訴 Docker 服務(wù)端容器暴露的端口號系吭,供互聯(lián)系統(tǒng)使用。在啟動容器時需要通過 -P残腌,Docker 主機(jī)會自動分配一個端口轉(zhuǎn)發(fā)到指定的端口村斟。

6. ENV

格式為 ENV <key> <value>。 指定一個環(huán)境變量抛猫,會被后續(xù) RUN 指令使用蟆盹,并在容器運(yùn)行時保持。
例如

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
ENV TZ=Asia/Shanghai
ENV PYTHONPATH=/usr/src/app

7. ADD

格式為 ADD <src> <dest>闺金。
該命令將復(fù)制指定的 <src> 到容器中的 <dest>逾滥。 其中 <src> 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL败匹;還可以是一個 tar 文件(自動解壓為目錄)寨昙。

8. COPY

格式為 COPY <src> <dest>。
復(fù)制本地主機(jī)的 <src>(為 Dockerfile 所在目錄的相對路徑)到容器中的 <dest>掀亩。
當(dāng)使用本地目錄為源目錄時舔哪,推薦使用 COPY。

9. ENTRYPOINT

兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中執(zhí)行)槽棍。
配置容器啟動后執(zhí)行的命令捉蚤,并且不可被 docker run 提供的參數(shù)覆蓋。
每個 Dockerfile 中只能有一個 ENTRYPOINT炼七,當(dāng)指定多個時缆巧,只有最后一個起效。

10. VOLUME

格式為 VOLUME ["/data"]豌拙。
創(chuàng)建一個可以從本地主機(jī)或其他容器掛載的掛載點(diǎn)陕悬,一般用來存放數(shù)據(jù)庫和需要保持的數(shù)據(jù)等。

11. USER

格式為 USER daemon按傅。
指定運(yùn)行容器時的用戶名或 UID捉超,后續(xù)的 RUN 也會使用指定用戶胧卤。
當(dāng)服務(wù)不需要管理員權(quán)限時,可以通過該命令指定運(yùn)行用戶拼岳。并且可以在之前創(chuàng)建所需要的用戶灌侣,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要臨時獲取管理員權(quán)限可以使用 gosu裂问,而不推薦 sudo侧啼。

12. WORKDIR

格式為 WORKDIR /path/to/workdir。
為后續(xù)的 RUN堪簿、CMD痊乾、ENTRYPOINT 指令配置工作目錄。
可以使用多個 WORKDIR 指令椭更,后續(xù)命令如果參數(shù)是相對路徑哪审,則會基于之前命令指定的路徑。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑為 /a/b/c虑瀑。

13. ONBUILD

格式為 ONBUILD [INSTRUCTION]湿滓。
配置當(dāng)所創(chuàng)建的鏡像作為其它新創(chuàng)建鏡像的基礎(chǔ)鏡像時,所執(zhí)行的操作指令舌狗。
ONBUILD指令,實(shí)際上就是相當(dāng)于創(chuàng)建一個模板鏡像叽奥,后續(xù)可以根據(jù)該模板鏡像創(chuàng)建特定的子鏡像
例如,Dockerfile 使用如下的內(nèi)容創(chuàng)建了鏡像 image-A痛侍。

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

image-A的構(gòu)建過程中不執(zhí)行這兩條命令朝氓,但在FROM image-A的子鏡像中會執(zhí)行這兩條命令。

二主届、構(gòu)建鏡像

docker build -t mynginx:v2019 .

注意不要少了最后面的“.”

三赵哲、Dockerfile編寫建議

  • 通過 Docker 多階段構(gòu)建將多個層壓縮為一個
    在構(gòu)建 Docker 容器時,應(yīng)該盡量想辦法獲得體積更小的鏡像君丁,因?yàn)閭鬏敽筒渴痼w積較小的鏡像速度更快枫夺。
    從 Docker 1.10 開始,COPY绘闷、ADD 和 RUN 語句會向鏡像中添加新層橡庞。層會占用空間,你擁有的層越多簸喂,最終的鏡像就越大毙死。Git 存儲庫在這方面也是類似的燎潮,存儲庫的大小隨著層數(shù)的增加而增加喻鳄,因?yàn)?Git 必須保存提交之間的所有變更。
  • 將不經(jīng)常改動的命令确封,比如python的reqirements.txt 依賴包除呵,單獨(dú)拎出來放在項(xiàng)目代碼的前面再菊。因?yàn)橐蕾嚢唤?jīng)常變動,每次生成鏡像時颜曾,只需將后面的項(xiàng)目代碼copy到鏡像即可纠拔。
# 方案一:
FROM python:3.6

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY . /usr/src/app
RUN pip install -r /usr/src/app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

CMD python /usr/src/app/manage.py runserver 0.0.0.0:8000


# 方案二:
FROM python:3.6

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/
RUN pip install -r /usr/src/app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

COPY . /usr/src/app
CMD python /usr/src/app/manage.py runserver 0.0.0.0:8000

方案二比方案一好,為什么泛豪?因?yàn)榉桨敢恢械膔equirements.txt實(shí)際項(xiàng)目中是很少變動稠诲,但是因?yàn)?usr/src/app的項(xiàng)目代碼是經(jīng)常變動,導(dǎo)致每次打包都得根據(jù)equirements.txt安裝依賴包诡曙。而方案二先把requirements.txt 拷貝進(jìn)來臀叙,如果requirements.txt 沒改動,docker會用到之前緩存的价卤,加快打包速度劝萤。
實(shí)際運(yùn)行幾次打包過程,會發(fā)現(xiàn)速度的差異是比較明顯的慎璧。

四床嫌、實(shí)踐

公司現(xiàn)在的所有項(xiàng)目均以容器封裝,幾十個容器運(yùn)行在十來臺主機(jī)中胸私,現(xiàn)在正在將服務(wù)器整合到kubernetes集群中厌处,可以說一切皆容器,一切皆Docker岁疼。

1. Django項(xiàng)目的Dockerfile

Django項(xiàng)目打包成Docker鏡像是比較簡單嘱蛋,主要是安裝python依賴包,然后就是manage.py啟動服務(wù)五续。
Dockerfile 位于Django項(xiàng)目的根目錄洒敏,目錄結(jié)構(gòu)如下:

├── requirements.txt
├── Dockerfile
├── api
│ ├── __init__.py
│ ├── urls.py
│ ├── wsgi.py
│ └── settings.py

Dockerfile文件:

FROM python:3.6

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/
RUN pip install -r /usr/src/app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

COPY . /usr/src/app

CMD python /usr/src/app/manage.py runserver 0.0.0.0:8000

2. SpringMVC項(xiàng)目的Dockerfile

項(xiàng)目運(yùn)行在tomcat中。
先生成war文件疙驾,轉(zhuǎn)成tar.gz文件凶伙, 通過ADD命令解壓到鏡像中。接下來就是配置文件的替換它碎,最后運(yùn)行tomact服務(wù)函荣。

# Version 0.1

# 基礎(chǔ)鏡像
FROM cbbing/tomcat

RUN rm -rf $CATALINA_HOME/webapps/ROOT
ADD ROOT.tar.gz $CATALINA_HOME/webapps/

# 配置文件替換
COPY conf/server.xml $CATALINA_HOME/conf/
COPY conf/tomcat-users.xml $CATALINA_HOME/conf/
COPY conf/jdbc.properties $CATALINA_HOME/webapps/ROOT/WEB-INF/classes/properties/

CMD ["catalina.sh", "run"]

mvn.sh: 生成ROOT.tar.gz的腳本如下:

cd ../myweb
mvn clean
mvn install -DskipTests

cd ..
mkdir ./ROOT
cp ./myweb/target/myweb.war ./ROOT

cd ROOT
jar xvf myweb.war
rm myweb.war
cd ..
tar czf ROOT.tar.gz ./ROOT
rm -rf ROOT/

3. Vue.js項(xiàng)目的Dockerfile

步驟如下:

  1. 下載package.json中定義的依賴
  2. npm build生成編譯后的文件到dist
  3. 基礎(chǔ)鏡像為nginx,從nginx代理靜態(tài)文件
FROM nginx:1.15

MAINTAINER cbbing <cbbing@163.com>

ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone

COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY dist /usr/share/nginx/html

make.sh:制作腳本如下

#!/usr/bin/env bash

echo "npm install"
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install

echo "npm build"
npm run build

image_tag=`date +%Y%m%d` #_%H%M
echo "當(dāng)前時間:$image_tag"
docker build -t cbbing/web_p:v${image_tag} .

4. Scrapy項(xiàng)目的Dockerfile

scrapy項(xiàng)目和Django項(xiàng)目的差別在于啟動的方式不同扳肛,這里涉及到一些配置文件傻挂。

FROM python:3.6

#設(shè)置時區(qū)
ENV TZ=Asia/Shanghai
ENV PYTHONPATH=/usr/src/app

RUN mkdir -p /usr/src/app \
    && pip install -r /root/.pip/requirements.txt  -i https://mirrors.aliyun.com/pypi/simple/ \
    && apt-get update \
    && apt-get install -y supervisor \
    && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && echo $TZ > /etc/timezone

WORKDIR /usr/src/app

COPY . /usr/src/app

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN mkdir -p /var/log/supervisor

COPY scrapyd.conf /usr/local/lib/python3.6/site-packages/scrapyd/default_scrapyd.conf

CMD ["/usr/bin/supervisord"]

其中用到的配置文件:

  • supervisord.conf
[inet_http_server]
port=9020
username=admin
password=1234

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log;
pidfile=/var/log/supervisord.pid;
childlogdir=/var/log/supervisor

[program:scrapyd]
command=scrapyd
loglevel=info
redirect_stderr=true
stdout_events_enabled=true

[program:scrapyd-deploy]
command=bash supervisor-scrapyd-deploy.sh
startsecs = 35
loglevel=info

[program:simple_http]
command=/bin/bash supervisor-http-egg.sh
autorestart=true
startsecs=10
loglevel=info

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
  • scrapyd.conf
[scrapyd]
eggs_dir = eggs
logs_dir = logs
items_dir =
jobs_to_keep = 20
dbs_dir = dbs
max_proc = 0
max_proc_per_cpu = 4
finished_to_keep = 100
poll_interval = 5.0
bind_address = 0.0.0.0
http_port = 6800
debug = off
runner = scrapyd.runner
application = scrapyd.app.application
launcher = scrapyd.launcher.Launcher
webroot = scrapyd.website.Root

[services]
schedule.json = scrapyd.webservice.Schedule
cancel.json = scrapyd.webservice.Cancel
addversion.json = scrapyd.webservice.AddVersion
listprojects.json = scrapyd.webservice.ListProjects
listversions.json = scrapyd.webservice.ListVersions
listspiders.json = scrapyd.webservice.ListSpiders
delproject.json = scrapyd.webservice.DeleteProject
delversion.json = scrapyd.webservice.DeleteVersion
listjobs.json = scrapyd.webservice.ListJobs
daemonstatus.json = scrapyd.webservice.DaemonStatus

參考

  1. Dockerfile介紹
  2. 三個技巧,將 Docker 鏡像體積減小 90%
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挖息,一起剝皮案震驚了整個濱河市金拒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖绪抛,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件资铡,死亡現(xiàn)場離奇詭異,居然都是意外死亡幢码,警方通過查閱死者的電腦和手機(jī)笤休,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來症副,“玉大人店雅,你說我怎么就攤上這事≌晗常” “怎么了底洗?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咕娄。 經(jīng)常有香客問我亥揖,道長,這世上最難降的妖魔是什么圣勒? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任费变,我火速辦了婚禮,結(jié)果婚禮上圣贸,老公的妹妹穿的比我還像新娘挚歧。我一直安慰自己,他們只是感情好吁峻,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布滑负。 她就那樣靜靜地躺著,像睡著了一般用含。 火紅的嫁衣襯著肌膚如雪矮慕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天啄骇,我揣著相機(jī)與錄音痴鳄,去河邊找鬼。 笑死缸夹,一個胖子當(dāng)著我的面吹牛痪寻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虽惭,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼橡类,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芽唇?” 一聲冷哼從身側(cè)響起顾画,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亲雪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疚膊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年义辕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寓盗。...
    茶點(diǎn)故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡灌砖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出傀蚌,到底是詐尸還是另有隱情基显,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布善炫,位于F島的核電站撩幽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏箩艺。R本人自食惡果不足惜窜醉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艺谆。 院中可真熱鬧榨惰,春花似錦、人聲如沸静汤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虫给。三九已至藤抡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抹估,已是汗流浹背杰捂。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棋蚌,地道東北人嫁佳。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像谷暮,于是被迫代替她去往敵國和親蒿往。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評論 2 361