摘要:正確的做法是直接執(zhí)行可執(zhí)行文件,并且要求以前臺(tái)形式運(yùn)行。官方鏡像官方鏡像在這里先定義了環(huán)境變量,其后的這層里,多次使用來(lái)進(jìn)行操作定制。只有當(dāng)以當(dāng)前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級(jí)鏡像的時(shí)候才會(huì)被執(zhí)行。
基礎(chǔ)命令
名稱 | 作用 | 示例 |
---|---|---|
docker systen df | 查看鏡像、容器、數(shù)據(jù)卷所占的空間 | |
docker images -q | 產(chǎn)生指定范圍的id列表 | docker image ls -q redis |
docker image rm $() | 批量刪除指定鏡像 | docker image rm $(docker image ls -q redis) |
docker run | 基于鏡像啟動(dòng)容器 | docker run --name webserver -d -p 80:80 nginx |
docker exec | 進(jìn)入容器 | docker exec -it webserver /bin/bash |
docker diff | 查看容器存儲(chǔ)層的改動(dòng) | docker diff webserver |
docker commit | 將容器的存儲(chǔ)層保存為鏡像 | docker commit [選項(xiàng)] <容器ID或容器名> [<倉(cāng)庫(kù)名>[:<標(biāo)簽>]] |
docker history | 具體查看鏡像歷史 | docker history nginx:v2 |
docker export | 導(dǎo)出本地容器 | docker export c422162c86da >mysql.tar |
docker import | 導(dǎo)入容器快照到本地鏡像倉(cāng)庫(kù) | cat mysql.tar | docker import - test/mysql:v1.0 |
docker save | 保存鏡像(推薦Docker Registry方式) | docker save docker.io/mysql | gzip > mysql-test.tar.gz |
docker load | 加載鏡像(推薦Docker Registry方式) | docker load -i mysql-test.tar.gz |
名稱 | 作用 | 示例 |
---|---|---|
FROM | 指定基礎(chǔ)鏡像 | FROM scratch 指定一個(gè)空白的鏡像 |
RUN | 用來(lái)執(zhí)行命令行命令的 | RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"] |
COPY | 從構(gòu)建上下文目錄中 <源路徑> 的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑> 位置 | COPY <源路徑>... <目標(biāo)路徑> |
ADD | 更高級(jí)的復(fù)制文件 | (幾乎不用它)所有復(fù)制文件用COPY,僅在需要自動(dòng)解壓縮的場(chǎng)合使用 ADD |
CMD | 容器啟動(dòng)命令 | 推薦使用 exec 格式 CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...] 注意是雙引號(hào) |
ENTRYPOINT | 入口點(diǎn) | 1 讓鏡像變成像命令一樣使用; 2 應(yīng)用運(yùn)行前的準(zhǔn)備工作 |
ENV | 設(shè)置環(huán)境變量 | ENV |
ARG | 構(gòu)建參數(shù) | ARG <參數(shù)名>[=<默認(rèn)值>] |
VOLUME | 定義匿名卷 | VOLUME ["<路徑1>", "<路徑2>"...] |
EXPOSE | 聲明運(yùn)行時(shí)容器提供服務(wù)端口 | EXPOSE <端口1> [<端口2>...] |
WORKDIR | 指定工作目錄 | WORKDIR <工作目錄路徑> |
USER | 指定當(dāng)前用戶 | USER <用戶名> |
HEALTHCHECK | 健康檢查 | HEALTHCHECK [選項(xiàng)] CMD <命令> :設(shè)置檢查容器健康狀況的命令 |
ONBUILD | 為他人做嫁衣 | ONBUILD <其它指令> |
介紹
Dockerfile 是一個(gè)文本文件,里面包含了一條條的指令,每一條指令構(gòu)建一層,因此每一條指令的內(nèi)容都是描述該層如何構(gòu)建。
使用dockerfile的好處
避免了docker commit方式帶來(lái)的臃腫,實(shí)際應(yīng)用中不應(yīng)采用docker commit.
基本流程
mkdir mynginx cd mynginx touch Dockerfile vim Dockerfile,寫(xiě)入 FROM nginx RUN echo "正確構(gòu)建Hello, Docker!
" > /usr/share/nginx/html/index.html 構(gòu)建鏡像 docker build -t nginx:v3 . # 注意最后面有一個(gè)點(diǎn) or docker build - < Dockerfile #從標(biāo)準(zhǔn)輸入中讀取 Dockerfile 進(jìn)行構(gòu)建 or cat Dockerfile | docker build - or docker build http://server/context.tar.gz #用給定的 tar 壓縮包構(gòu)建 or docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14 # 直接用 Git repo 進(jìn)行構(gòu)建 or docker build - < context.tar.gz # 從標(biāo)準(zhǔn)輸入中讀取上下文壓縮包進(jìn)行構(gòu)建
Dockerfile 中每一個(gè)指令都會(huì)建立一層, RUN 也不例外。每一個(gè) RUN 的行為, 就和剛才我們手工建立鏡像的過(guò)程一樣:新建立一層,在其上執(zhí)行這些命令,執(zhí)行結(jié)束 后, commit 這一層的修改,構(gòu)成新的鏡像。錯(cuò)誤的示例
FROM debian:jessie RUN apt-get update RUN apt-get install -y gcc libc6-dev make RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install正確的寫(xiě)法
FROM debian:jessie RUN buildDeps="gcc libc6-dev make" && apt-get update && apt-get install -y $buildDeps && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" && mkdir -p /usr/src/redis && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 && make -C /usr/src/redis && make -C /usr/src/redis install && rm -rf /var/lib/apt/lists/* && rm redis.tar.gz && rm -r /usr/src/redis && apt-get purge -y --auto-remove $buildDeps關(guān)于上下文
COPY ./package.json /app/ 這并不是要復(fù)制執(zhí)行 docker build 命令所在的目錄下的 package.json ,也不是復(fù)制 Dockerfile 所在目錄下的 package.json ,而是復(fù)制 上下文(context) 目錄下的 package.jsonADD
FROM scratch ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz / ...CMD
shell格式: CMD echo $HOME 實(shí)際執(zhí)行: CMD [ "sh", "-c", "echo $HOME" ] Docker 不是虛擬機(jī),容器中的應(yīng)用都應(yīng)該以前臺(tái)執(zhí)行,而不是像虛擬機(jī)、物理機(jī)里面那樣, 用 upstart/systemd 去啟動(dòng)后臺(tái)服務(wù),容器內(nèi)沒(méi)有后臺(tái)服務(wù)的概念。 CMD service nginx start 這個(gè)命令會(huì)被理解為 CMD [ "sh", "-c", "service nginx start"] ,因此主進(jìn)程實(shí)際上是 sh 。 那么當(dāng) service nginx start 命令結(jié)束后, sh 也就結(jié)束了, sh 作為主進(jìn)程退出了,自然就會(huì)令容器退出。 正確的做法是直接執(zhí)行 nginx 可執(zhí)行文件,并且要求以前臺(tái)形式運(yùn)行。比如: CMD ["nginx", "-g", "daemon off;"]ENTRYPOINT
場(chǎng)景一:讓鏡像變成像命令一樣使用
錯(cuò)誤的示范
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* CMD [ "curl", "-s", "http://ip.cn" ] docker build -t myip . docker run myip docker run myip -i # 如果加上-i參數(shù),就會(huì)報(bào)錯(cuò)
正確的示范
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
場(chǎng)景二:應(yīng)用運(yùn)行前的準(zhǔn)備工作
啟動(dòng)容器就是啟動(dòng)主進(jìn)程,但有些時(shí)候,啟動(dòng)主進(jìn)程前,需要一些準(zhǔn)備工作。 官方redis鏡像 FROM alpine:3.4 ... RUN addgroup -S redis && adduser -S -G redis redis ... ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 6379 CMD [ "redis-server" ]
docker-entrypoint.sh #!/bin/sh ... # allow the container to be started with `--user` if [ "$1" = "redis-server" -a "$(id -u)" = "0" ]; then chown -R redis . exec su-exec redis "$0" "$@" fi exec "$@"ENV
官方node鏡像 ENV NODE_VERSION 7.2.0 RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.ta r.xz" && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc && grep " node-v$NODE_VERSION-linux-x64.tar.xz$" SHASUMS256.txt | sha256sum -c - && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components= 1 && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt && ln -s /usr/local/bin/node /usr/local/bin/nodejs 在這里先定義了環(huán)境變量 NODE_VERSION ,其后的 RUN 這層里,多次使用 $NODE_VERSION 來(lái)進(jìn)行操作定制。 可以看到,將來(lái)升級(jí)鏡像構(gòu)建版本的時(shí)候,只需要更新 7.2.0 即可, Dockerfile 構(gòu)建維護(hù)變得更輕松了。 下列指令可以支持環(huán)境變量展開(kāi): ADD 、 COPY 、 ENV 、 EXPOSE 、 LABEL 、 USER 、 WORKDIR 、 VOLUME 、 STOPSIGNAL 、 ONBUILD 。ARG
Dockerfile 中的 ARG 指令是定義參數(shù)名稱,以及定義其默認(rèn)值。該默認(rèn)值可以在構(gòu)建命令 docker build 中用 --build-arg <參數(shù)名>=<值> 來(lái)覆蓋。VOLUME
VOLUME /data 這里的 /data 目錄就會(huì)在運(yùn)行時(shí)自動(dòng)掛載為匿名卷,任何向 /data 中寫(xiě)入的信息都不會(huì)記錄進(jìn)容器存儲(chǔ)層, 從而保證了容器存儲(chǔ)層的無(wú)狀態(tài)化。當(dāng)然,運(yùn)行時(shí)可以覆蓋這個(gè)掛載設(shè)置。 docker run -d -v mydata:/data xxxx 在這行命令中,就使用了 mydata 這個(gè)命名卷掛載到了 /data 這個(gè)位置,替代了Dockerfile 中定義的匿名卷的掛載配置。EXPOSE
要將 EXPOSE 和在運(yùn)行時(shí)使用 -p <宿主端口>:<容器端口> 區(qū)分開(kāi)來(lái)。 -p ,是映射宿主端口和 容器端口,換句話說(shuō),就是將容器的對(duì)應(yīng)端口服務(wù)公開(kāi)給外界訪問(wèn),而 EXPOSE 僅僅是聲明 容器打算使用什么端口而已,并不會(huì)自動(dòng)在宿主進(jìn)行端口映射WORKDIR
錯(cuò)誤的示例
初學(xué)者常犯的錯(cuò)誤是把 Dockerfile 等同于 Shell 腳本來(lái)書(shū)寫(xiě) RUN cd /app RUN echo "hello" > world.txt 如果需要改變以后各層的工作目錄的位置,那么應(yīng)該使用 WORKDIR 指令USER
USER 指令和 WORKDIR 相似,都是改變環(huán)境狀態(tài)并影響以后的層,用戶需提前建好. RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN [ "redis-server" ]HEALTHCHECK
FROM nginx RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1 這里我們?cè)O(shè)置了每 5 秒檢查一次(這里為了試驗(yàn)所以間隔非常短,實(shí)際應(yīng)該相對(duì)較長(zhǎng)),如 果健康檢查命令超過(guò) 3 秒沒(méi)響應(yīng)就視為失敗,并且使用 curl -fs http://localhost/ || exit 1 作為健康檢查命令。 查看 docker inspect --format "{{json .State.Health}}" web | python -m json.toolONBUILD
ONBUILD 是一個(gè)特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而這些指令, 在當(dāng)前鏡像構(gòu)建時(shí)并不會(huì)被執(zhí)行。只有當(dāng)以當(dāng)前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級(jí)鏡像的時(shí)候才會(huì)被執(zhí)行。 Dockerfile 中的其它指令都是為了定制當(dāng)前鏡像而準(zhǔn)備的,唯有 ONBUILD 是為了幫助別人定制自己而準(zhǔn)備的。
假設(shè)一個(gè)node.js的dockerfile如下
FROM node:slim RUN mkdir /app WORKDIR /app COPY ./package.json /app RUN [ "npm", "install" ] COPY . /app/ CMD [ "npm", "start" ]
現(xiàn)在有其他的鏡像依賴這個(gè)鏡像,假設(shè)基礎(chǔ)鏡像叫my-node
FROM node:slim RUN mkdir /app WORKDIR /app CMD [ "npm", "start" ]
那么其他依賴的子項(xiàng)目的鏡像為
FROM my-node COPY ./package.json /app RUN [ "npm", "install" ] COPY . /app/ 基礎(chǔ)鏡像變化后,各個(gè)項(xiàng)目都用這個(gè) Dockerfile 重新構(gòu)建鏡像,會(huì)繼承基礎(chǔ)鏡像的更新 但是問(wèn)題只解決了一半,如果這個(gè)子Dockerfile 里面有些東西需要調(diào)整呢? 比如 npm install 都需要加一些參數(shù),那怎么辦?這一行 RUN 是不可能放入基礎(chǔ)鏡像的, 因?yàn)樯婕暗搅水?dāng)前項(xiàng)目的 ./package.json ,難道又要一個(gè)個(gè)修改么? 所以說(shuō),這樣制作基礎(chǔ)鏡像,只解決了原來(lái)的 Dockerfile 的前4條指令的變化問(wèn)題, 而后面三條指令的變化則完全沒(méi)辦法處理。
用ONBUILD重寫(xiě)基礎(chǔ)鏡像
FROM node:slim RUN mkdir /app WORKDIR /app ONBUILD COPY ./package.json /app ONBUILD RUN [ "npm", "install" ] ONBUILD COPY . /app/ CMD [ "npm", "start" ] 在用ONBUILD構(gòu)建基礎(chǔ)鏡像的時(shí)候,這三行并不會(huì)被執(zhí)行
那么子鏡像只需
FROM my-node 當(dāng)在各個(gè)項(xiàng)目目錄中,用這個(gè)只有一行的 Dockerfile 構(gòu)建鏡像時(shí),之前基礎(chǔ)鏡像的那三行 ONBUILD 就會(huì)開(kāi)始執(zhí)行, 成功的將當(dāng)前項(xiàng)目的代碼復(fù)制進(jìn)鏡像、并且針對(duì)本項(xiàng)目執(zhí)行 npm install ,生成應(yīng)用鏡像參考文檔
Docker 從入門到實(shí)踐
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/27405.html
摘要:導(dǎo)讀要從容器化開(kāi)始,而容器又需要從開(kāi)始,本文將介紹如何寫(xiě)出一個(gè)優(yōu)雅的文件。只要記住以上三點(diǎn)就能寫(xiě)出不錯(cuò)的。執(zhí)行完成項(xiàng)目的構(gòu)建。 導(dǎo)讀 Kubernetes要從容器化開(kāi)始,而容器又需要從Dockerfile開(kāi)始,本文將介紹如何寫(xiě)出一個(gè)優(yōu)雅的Dockerfile文件。 文章主要內(nèi)容包括: Docker容器 Dockerfile 使用多階構(gòu)建 感謝公司提供大量機(jī)器資源及時(shí)間讓我們可以實(shí)踐...
摘要:用于配置當(dāng)前所創(chuàng)建的鏡像作為其它新創(chuàng)建鏡像的基礎(chǔ)鏡像時(shí),所執(zhí)行的操作指令。運(yùn)行構(gòu)建命令構(gòu)建命令用于使用創(chuàng)建鏡像。 本文旨在用通俗的語(yǔ)言講述枯燥的知識(shí) 前面講到鏡像的構(gòu)建時(shí),講述的是用commit的方式構(gòu)建鏡像,而Dockerfile是另一種構(gòu)建鏡像的方式。 Dockerfile構(gòu)建鏡像是以基礎(chǔ)鏡像為基礎(chǔ)的,Dockerfile是一個(gè)文本文件,內(nèi)容是用戶編寫(xiě)的一些docker指令,每一條...
摘要:我們可以了解到,鏡像的定制實(shí)際上就是定制每一層所添加的配置文件。指令之指令的目的就是來(lái)指定基礎(chǔ)鏡像。指令之指令是用來(lái)執(zhí)行命令行命令的。由于命令行的強(qiáng)大能力,指令在定制鏡像時(shí)是最常用的指令之一。構(gòu)建鏡像這里我們使用了命令進(jìn)行鏡像構(gòu)建。 我們可以了解到,鏡像的定制實(shí)際上就是定制每一層所添加的配置、文件。如果我們可以把每一層修改、安裝、構(gòu)建、操作的命令都寫(xiě)入一個(gè)腳本,用這個(gè)腳本來(lái)構(gòu)建、定制鏡...
摘要:本文已獲得原作者授權(quán)。在構(gòu)建鏡像的過(guò)程中會(huì)緩存一系列中間鏡像。鏡像時(shí),會(huì)順序執(zhí)行中的指令,并同時(shí)比較當(dāng)前指令和其基礎(chǔ)鏡像的所有子鏡像,若發(fā)現(xiàn)有一個(gè)子鏡像也是由相同的指令生成,則命中緩存,同時(shí)可以直接使用該子鏡像而避免再去重新生成了。 本文已獲得原作者 CodeSheep 授權(quán)。 概述 Dockerfile 是專門用來(lái)進(jìn)行自動(dòng)化構(gòu)建鏡像的編排文件(就像 Jenkins 2.0時(shí)代的 J...
摘要:前言自動(dòng)化構(gòu)建是應(yīng)用發(fā)布過(guò)程中必不可少的環(huán)節(jié),常用的構(gòu)建工具有等。當(dāng)然,我推薦個(gè)人體驗(yàn)的話就用官方的吧,因?yàn)檫@樣你構(gòu)建的鏡像還可以與他人共享。 前言 自動(dòng)化構(gòu)建是應(yīng)用發(fā)布過(guò)程中必不可少的環(huán)節(jié), 常用的構(gòu)建工具有jenkins ,walle 等。而這些工具在構(gòu)建應(yīng)用時(shí)通常會(huì)有以下問(wèn)題: 需要直接或間接的寫(xiě)一坨用于構(gòu)建的shell命令等,不易管理、兼容性較差 上面一點(diǎn)可能還比較容易解決,...
摘要:但是看了下,里面的軟件源還是官方的,而且沒(méi)有安裝,所以就打算自己寫(xiě)一個(gè),用它來(lái)構(gòu)建適合自己的基礎(chǔ)鏡像。我事先配置好的,都是些基礎(chǔ)的配置。添加的文件必須以構(gòu)建上下文為根目錄來(lái)找,不能超出構(gòu)建上下文的范圍。 我們可以從Docker Hub上下載官方倉(cāng)庫(kù)中的鏡像,我自己就下載了ubuntu鏡像,只有188M左右,很小巧了。但是看了下,里面的軟件源還是官方的,而且沒(méi)有安裝vim,所以就打...
閱讀 3296·2021-11-24 09:39
閱讀 2804·2021-10-12 10:20
閱讀 1906·2019-08-30 15:53
閱讀 3075·2019-08-30 14:14
閱讀 2600·2019-08-29 15:36
閱讀 1120·2019-08-29 14:11
閱讀 1955·2019-08-26 13:51
閱讀 3407·2019-08-26 13:23