程式語言初學者 Docker 入門第八章 —— 使用 Dockerfile 建立映像檔
Dockerfile 是一個文字格式的設定檔,使用者可以使用 Dockerfile 快速建立自訂的映像檔
1. 基本結構
以行為單位的命語句所組成,並且支援以 # 開頭標示為註解行。
由 4 部分組成
-
基礎印象檔資訊
第一行必需指定基於的基礎映像檔,若欲建立基礎映像檔則可使用 scratch 空白印象檔
FROM ubuntu -
維護者資訊
docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com
-
映像檔操作指令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
-
容器啟動時需執行指令
CMD /usr/sbni/nginx
# This dockerfile uses the ubuntu image
# Version 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
2. 指令說明
1. FROM
所有 Dockerfile 中的第一道指令
建立多個映像檔,可以使用多個 FROM
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
2. MAINTAINER
MAINTAINER <name>
MAINTAINER image_creator@docker.com
該資訊會寫入產程映像檔的 Author 名稱屬性中
3. RUN
運行指定命令
格式為 RUN <command> or RUN ["executable", "param1", "param2"]
後面的指令會被解析為 JSON,必需用雙引號
前者預設在 shell 終端中執行命令 /bin/sh -c; 後者使用 exec 執行,不會啟動 shell 環境
指定使用其他終端類型可以透過第二種方式實現
RUN ["/bin/bash", "-c", "echo hello"]
每條 RUN 指令將在目前映像檔之基礎上執行指定命令,並交付成為新的映像檔,當命令較長時,可以使用 \ 來換行。
RUN apt-get update \\
&& apt-get install -y libsnappy-dev zlib1g-dev libbz2-dev \\
&& rm -rf /var/cache/apt
4. CMD
指定啟動容器試射執行的命令。他支援三種格式
- 推薦:CMD ["executable", "param1", "param2"] 使用 exec 執行
- CMD command param1 param2 會在 /bin/sh 中執行,提供給需要交互作用的應用程式
- CMD ["param1", "param2"] 提供給 ENTRYPOINT 的預設參數
每個 Dockerfile 只能有一條 CMD 命令。如果指定多條命令,只有最後一個會被執行
如果使用者在啟動容器時手動指定了欲執行之命令 (docker run 時的參數),則會覆蓋掉 CMD 指定的命令
5. LABEL
LABEL 指令用來指定產程映像檔的中繼資料標籤資訊。
格式 LABEL <key>=<value> <key>=<value> <key>=<value> ...。
例如:
LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."
6. EXPOSE
宣告映像檔內服務所監聽的連接埠
EXPOSE <port> [<port>...] (HOSTPORT)
EXPOSE 22 80 8443
該指令只是達到宣告作用,不會自動完成連接埠對應
在啟動容器時需要使用 -P
,Docker 主機會自動分配一個 Host 主機的臨時連接埠轉發到容器內指定的連接埠; -p
則可以具體指定 Host 主機的哪個連接埠來對應。
7. ENV
指定環境變數,在映像檔產生過程中會被後續 RUN 指令所使用,以此印象檔啟動的容器中也會存在。
格式: ENV<key><value> 或 ENV<key>=<value>...
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL <http://example.com/postfres-$PG_VERSION.tar.xz> | tar -xJC /usr/src/postgress && ...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
指令所指定的環境變數在執行時仍可以被覆蓋掉: docker run --env <key≥<value> built_image
8. ADD
格式: ADD<src> <dest>
<src>: 本地端主機 Dockerfile 所在目錄的相對路徑,
- 檔案或目錄。不能使用 ../something 和絕對路徑。
- URL
- tar 壓縮檔,會自動姐壓縮到 <dest> 路徑下
<dest>: 映像檔的絕對路徑,或者相對於於 WORKDIR 的相對路徑
支援萬用符格式:ADD *.c /code/
9. COPY
格式: COPY<src> <dest>
<src>: 本地端主機 Dockerfile 所在目錄的相對路徑,檔案或目錄
<dest>: src 要複製到映像檔中的路徑,不存在會新增
當使用本地目錄為原始來源時,推薦使用 COPY
10. ENTRYPOINT
指定映像檔的預設進入點,該進入點另命會在啟動容器時成為唯一另另執行,所有傳入值皆為該命令的參數
-
exec 方式執行
ENTRYPOINT ["executable", "param1", "param2"]
-
shell 中執行
ENTRYPOINT command param1 param2
11. VOLUME
建立資料卷掛載點,多為資料庫和需要持久保存的資料
格式: VOLUME ["/data"]
來源:本機或其他容器可掛載的資料卷
12. USER
13. WORKDIR
為後續 RUN, CMD, ENTRYPOINT 指令設定執行的工作目錄
格式: WORKDIR /path/to/workdir
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終路徑會是 /a/b/c
14. ARG
指定映像檔內使用的參數
15. ONBUILD
配置當所建立的映像檔成為其他映像檔之基礎映像檔時,所必定執行的建置操作指令
格式: ONBUILD [INSTRUCTION]
例如 Dockerfile 使用如下的內容建立了映像檔 image-A
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
如果基於 image-A 建立新的映像檔時,新的 Dockerfile 中使用 FROM image-A 指定為基礎映像檔,並會自動執行 ONBUILD 指令的內容
FROM image-A
以下指令會自動執行
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
有使用此指令的映像檔,建議在標籤中註明
ex: ruby:1.9-onbuild
16. STOPSIGNAL
17. HEALTHCHECK
設置所啟動容器該如何進行狀態檢查
18. SHELL
格式:SHELL ["executable", "parameters"]
預設為 ["/bin/bash", "-c"]
3. 建立映像檔
編寫完 Dockerfile 後可以透過 docker build
來建立映像檔
格式: docker build [選項] 內容路徑
$ docker build -t build_repi/first_image /tmp/docker_builder
<映像檔標籤> <Dockerfile 所在路徑>
指定 Dockerfile 所在路徑為 /tmp/docker_builder/,並且希望產生映像檔標籤為 build_repo/first_image
$ docker build -t docker_build/first_image /home/seraphine/workspace/ccclub-api/
Sending build context to Docker daemon 976.9kB
Step 1/13 : FROM python:3.7-alpine
---> 078bbc5dc0e6
Step 2/13 : WORKDIR /usr/src/app
---> Using cache
---> 7591691636db
Step 3/13 : ENV PYTHONDONTWRITEBYTECODE 1
---> Using cache
---> 43e64a551189
Step 4/13 : ENV PYTHONUNBUFFERED 1
---> Using cache
---> 1b0c1b79d3f0
Step 5/13 : RUN apk update && apk add postgresql-dev gcc python3-dev musl-dev jpeg-dev zlib-dev
---> Using cache
---> e953b47702be
Step 6/13 : RUN pip install --upgrade pip
---> Using cache
---> 3ac60eac560c
Step 7/13 : COPY ./requirements.txt /usr/src/app/requirements.txt
---> Using cache
---> 778a99f44a6e
Step 8/13 : RUN pip install -r requirements.txt
---> Using cache
---> f200dbd01d70
Step 9/13 : COPY . /usr/src/app/
---> Using cache
---> 4d2ea928202c
Step 10/13 : COPY ./entrypoint.sh /usr/src/app/entrypoint.sh
---> Using cache
---> 851525a35a14
Step 11/13 : RUN chmod +x /usr/src/app/entrypoint.sh
---> Using cache
---> e56669cb2d69
Step 12/13 : EXPOSE 80
---> Using cache
---> 0cdb6a5f9865
Step 13/13 : ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
---> Using cache
---> 6b4acf541a79
Successfully built 6b4acf541a79
Successfully tagged docker_build/first_image:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_build/first_image latest 6b4acf541a79 2 minutes ago 579MB
4. 使用 .dockerignore 檔
可以藉由此檔案,每行新增一行排除模式 exclusion patterns 來讓 Docker 忽略比對模式路徑下的目錄和檔案
*/timp*
*/*/temp*
tmp?
~*
5. 從映像檔產生 Dockerfile
範例:CenturyLinkLabs 釋出 dockerfile-from-image 的工具,可以逆向工程用 image 建立出 Dockerfile
$ docker run -v /run/docker.sock:/run/docker.sock centurylink/dockerfile-from-image
Usage: dockerfile-from-image.rb [options] <image_id>
-f, --full-tree Generate Dockerfile for all parent layers
-h, --help Show this message
docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage -sV=1.36 nginx:latest
$ docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage -sV=1.36 nginx:latest
Unable to find image 'alpine/dfimage:latest' locally
latest: Pulling from alpine/dfimage
df20fa9351a1: Pull complete
820dbffe2156: Pull complete
Digest: sha256:4a271e763d51b7f3cca72eac9bf508502c032665dde0e4c8d5fcf6376600f64a
Status: Downloaded newer image for alpine/dfimage:latest
Analyzing nginx:latest
Docker Version: 19.03.12
GraphDriver: overlay2
Environment Variables
|PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|NGINX_VERSION=1.21.0
|NJS_VERSION=0.5.3
|PKG_RELEASE=1~buster
Open Ports
|80
Image user
|User is root
Potential secrets:
Dockerfile:
CMD ["bash"]
LABEL maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>
ENV NGINX_VERSION=1.21.0
ENV NJS_VERSION=0.5.3
ENV PKG_RELEASE=1~buster
RUN set -x \\
&& addgroup --system --gid 101 nginx \\
&& adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \\
&& apt-get update \\
&& apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \\
&& NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; found=''; for server in ha.pool.sks-keyservers.net hkp://keyserver.ubuntu.com:80 hkp://p80.pool.sks-keyservers.net:80 pgp.mit.edu ; do echo "Fetching GPG key $NGINX_GPGKEY from $server"; apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" \\
&& found=yes \\
&& break; done; test -z "$found" \\
&& echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" \\
&& exit 1; apt-get remove --purge --auto-remove -y gnupg1 \\
&& rm -rf /var/lib/apt/lists/* \\
&& dpkgArch="$(dpkg --print-architecture)" \\
&& nginxPackages=" nginx=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} " \\
&& case "$dpkgArch" in amd64|i386|arm64) echo "deb <https://nginx.org/packages/mainline/debian/> buster nginx" >> /etc/apt/sources.list.d/nginx.list \\
&& apt-get update ;; *) echo "deb-src <https://nginx.org/packages/mainline/debian/> buster nginx" >> /etc/apt/sources.list.d/nginx.list \\
&& tempDir="$(mktemp -d)" \\
&& chmod 777 "$tempDir" \\
&& savedAptMark="$(apt-mark showmanual)" \\
&& apt-get update \\
&& apt-get build-dep -y $nginxPackages \\
&& ( cd "$tempDir" \\
&& DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" apt-get source --compile $nginxPackages ) \\
&& apt-mark showmanual | xargs apt-mark auto > /dev/null \\
&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \\
&& ls -lAFh "$tempDir" \\
&& ( cd "$tempDir" \\
&& dpkg-scanpackages . > Packages ) \\
&& grep '^Package: ' "$tempDir/Packages" \\
&& echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \\
&& apt-get -o Acquire::GzipIndexes=false update ;; esac \\
&& apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages gettext-base curl \\
&& apt-get remove --purge --auto-remove -y \\
&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \\
&& if [ -n "$tempDir" ]; then apt-get purge -y --auto-remove \\
&& rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; fi \\
&& ln -sf /dev/stdout /var/log/nginx/access.log \\
&& ln -sf /dev/stderr /var/log/nginx/error.log \\
&& mkdir /docker-entrypoint.d
COPY file:65504f71f5855ca017fb64d502ce873a31b2e0decd75297a8fb0a287f97acf92 in /
docker-entrypoint.sh
COPY file:0b866ff3fc1ef5b03c4e6c8c513ae014f691fb05d530257dfffd07035c1b75da in /docker-entrypoint.d
docker-entrypoint.d/
docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
COPY file:0fd5fca330dcd6a7de297435e32af634f29f7132ed0550d342cad9fd20158258 in /docker-entrypoint.d
docker-entrypoint.d/
docker-entrypoint.d/20-envsubst-on-templates.sh
COPY file:09a214a3e07c919af2fb2d7c749ccbc446b8c10eb217366e5a65640ee9edcc25 in /docker-entrypoint.d
docker-entrypoint.d/
docker-entrypoint.d/30-tune-worker-processes.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx" "-g" "daemon off;"]
Comments
Post a Comment