前几章算是docker的基础介绍,从第九章开始我们就要讲一点狠东西了
也不算高级的,但是是狠货
一.Dockerfile
1.1Dockerfile是什么
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。 网络
官网对Dockerfile的介绍是这样的
Docker can build images automatically by reading the instructions from a Dockerfile
. A Dockerfile
is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build
users can create an automated build that executes several command-line instructions in succession.
大概翻译:docker可以通过Dockerfile的指令自动地构建镜像。一个Dockerfile是一个文本文件,它包含了一个用户组建一个镜像所需要的全部命令。docker build指令,用户可以创建一个自动构建通过执行一系列的命令行指令。(ps:笔者英语水平不太好,即兴翻译,如果翻译不妥的地方,多担待)
1.2构建三部曲:
首先编写Dockerfile文件
第二,docker build命令构建镜像
最后docker run运行容器实例
1.3构建指令
docker build .
老规矩,我们看一下帮助手册:
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default "default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
其实参数也不多,我们后面再对这些参数进行讲解,今天先把Dockerfile的流程打通
1.4Dockerfile内容基础知识
最最最重要的一点:
编写Dockerfile的时候,名字一定要叫做Dockerfile
没错,就是需要一字不落的!
而且首字母需要大写
然后就是基础知识:
a.每条保留字指令都必须为大写字母且后面要跟随至少一个参数
b.指令按照从上到下,顺序执行
c.#表示注释
d.每条指令都会创建一个新的镜像层并对镜像进行提交
1.5docker执行Dockerfile的大致流程
a.docker从基础镜像运行一个容器
b.执行一条指令并对容器做出修改
c.执行类似docker commit的操作提交一个新的镜像层
d.docker在基于刚刚提交的镜像运行一个新容器
e.执行Dockerfile中的下一条指令直到所有指令都执行完成
我们这里可以参看一下tomcat官方的Dockerfile的模板
{{
include "from"
;
def is_apt:
vendor_variant | (
startswith("openjdk")
or startswith("temurin")
)
;
def major:
env.version | split(".")[0]
-}}
FROM {{ from }}
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
# see https://www.apache.org/dist/tomcat/tomcat-{{ major }}/KEYS
# see also "versions.sh" (https://github.com/docker-library/tomcat/blob/master/versions.sh)
ENV GPG_KEYS {{
# docker run --rm buildpack-deps:bullseye-curl bash -c 'wget -qO- https://www.apache.org/dist/tomcat/tomcat-10/KEYS | gpg --batch --import &> /dev/null && gpg --batch --list-keys --with-fingerprint --with-colons' | awk -F: '$1 == "pub" && $2 == "-" { pub = 1 } pub && $1 == "fpr" { fpr = $10 } $1 == "sub" { pub = 0 } pub && fpr && $1 == "uid" && $2 == "-" { print "\t\t\t#", $10; print "\t\t\t\"" fpr "\","; pub = 0 } END { print "\t\t\t# trailing comma 👀\n\t\t\tempty" }'
{
"10": [
# Mark E D Thomas <markt@apache.org>
"A9C5DF4D22E99998D9875A5110C01C5A2F6059E7",
# trailing comma 👀
empty
],
"9": [
# Mark E D Thomas <markt@apache.org>
"DCFD35E0BF8CA7344752DE8B6FB21E8933C60243",
# Mark E D Thomas <markt@apache.org>
"A9C5DF4D22E99998D9875A5110C01C5A2F6059E7",
# Remy Maucherat <remm@apache.org>
"48F8E69F6390C9F25CFEDCD268248959359E722B",
# trailing comma 👀
empty
],
"8": [
# Andy Armstrong <andy@tagish.com>
"79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED",
# Jean-Frederic Clere (jfclere) <JFrederic.Clere@fujitsu-siemens.com>
"05AB33110949707C93A279E3D3EFE6B686867BA6",
# kevin seguin <seguin@apache.org>
"A27677289986DB50844682F8ACB77FC2E86E29AC",
# Henri Gomez <hgomez@users.sourceforge.net>
"47309207D818FFD8DCD3F83F1931D684307A10A5",
# Yoav Shapira <yoavs@apache.org>
"07E48665A34DCAFAE522E5E6266191C37C037D42",
# Mark E D Thomas <markt@apache.org>
"DCFD35E0BF8CA7344752DE8B6FB21E8933C60243",
# Mark E D Thomas <markt@apache.org>
"A9C5DF4D22E99998D9875A5110C01C5A2F6059E7",
# Rémy Maucherat <remm@apache.org>
"541FBE7D8F78B25E055DDEE13C370389288584E7",
# Yoav Shapira <yoavs@computer.org>
"F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE",
# Tim Whittington (CODE SIGNING KEY) <timw@apache.org>
"9BA44C2621385CB966EBA586F72C284D731FABEE",
# Mladen Turk (Default signing key) <mturk@apache.org>
"F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23",
# Konstantin Kolinko (CODE SIGNING KEY) <kkolinko@apache.org>
"765908099ACF92702C7D949BFA0C35EA8AA299F1",
# Christopher Schultz <chris@christopherschultz.net>
"5C3C5F3E314C866292F359A8F3AD5C94A67F707E",
# trailing comma 👀
empty
],
} | .[major] // error("missing GPG keys")
| sort
| join(" ")
}}
ENV TOMCAT_MAJOR {{ major }}
ENV TOMCAT_VERSION {{ .version }}
ENV TOMCAT_SHA512 {{ .sha512 }}
{{ if java_variant == "jdk" then ( -}}
RUN set -eux; \
\
{{ if is_apt then ( -}}
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
curl \
dirmngr \
gnupg \
; \
{{ ) else ( -}}
# http://yum.baseurl.org/wiki/YumDB.html
if ! command -v yumdb > /dev/null; then \
yum install -y yum-utils; \
yumdb set reason dep yum-utils; \
fi; \
# a helper function to "yum install" things, but only if they aren't installed (and to set their "reason" to "dep" so "yum autoremove" can purge them for us)
_yum_install_temporary() { ( set -eu +x; \
local pkg todo=''; \
for pkg; do \
if ! rpm --query "$pkg" > /dev/null 2>&1; then \
todo="$todo $pkg"; \
fi; \
done; \
if [ -n "$todo" ]; then \
set -x; \
yum install -y $todo; \
yumdb set reason dep $todo; \
fi; \
) }; \
_yum_install_temporary gzip tar; \
{{ ) end -}}
\
ddist() { \
local f="$1"; shift; \
local distFile="$1"; shift; \
local mvnFile="${1:-}"; \
local success=; \
local distUrl=; \
for distUrl in \
# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
"https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile" \
# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
"https://downloads.apache.org/$distFile" \
"https://www-us.apache.org/dist/$distFile" \
"https://www.apache.org/dist/$distFile" \
"https://archive.apache.org/dist/$distFile" \
# if all else fails, let's try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} \
; do \
if curl -fL -o "$f" "$distUrl" && [ -s "$f" ]; then \
success=1; \
break; \
fi; \
done; \
[ -n "$success" ]; \
}; \
\
ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; \
echo "$TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
tar -xf tomcat.tar.gz --strip-components=1; \
rm bin/*.bat; \
rm tomcat.tar.gz*; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME"; \
\
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
mv webapps webapps.dist; \
mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
\
nativeBuildDir="$(mktemp -d)"; \
tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
{{ if is_apt then ( -}}
apt-get install -y --no-install-recommends \
dpkg-dev \
gcc \
libapr1-dev \
libssl-dev \
make \
; \
{{ ) else ( -}}
_yum_install_temporary \
apr-devel \
gcc \
make \
openssl11-devel \
; \
{{ ) end -}}
( \
export CATALINA_HOME="$PWD"; \
cd "$nativeBuildDir/native"; \
{{ if is_apt then ( -}}
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
{{ ) else "" end -}}
aprConfig="$(command -v apr-1-config)"; \
./configure \
{{ if is_apt then ( -}}
--build="$gnuArch" \
{{ ) else "" end -}}
--libdir="$TOMCAT_NATIVE_LIBDIR" \
--prefix="$CATALINA_HOME" \
--with-apr="$aprConfig" \
--with-java-home="$JAVA_HOME" \
--with-ssl=yes \
; \
nproc="$(nproc)"; \
make -j "$nproc"; \
make install; \
); \
rm -rf "$nativeBuildDir"; \
rm bin/tomcat-native.tar.gz; \
\
{{ if is_apt then ( -}}
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| xargs -rt readlink -e \
| sort -u \
| xargs -rt dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" \
| xargs -r apt-mark manual \
; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
{{ ) else ( -}}
# mark any explicit dependencies as manually installed
find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ && $(NF-1) != "=>" { print $(NF-1) }' \
| xargs -rt readlink -e \
| sort -u \
| xargs -rt rpm --query --whatprovides \
| sort -u \
| tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" \
| xargs -r yumdb set reason user \
; \
\
# clean up anything added temporarily and not later marked as necessary
yum autoremove -y; \
yum clean all; \
rm -rf /var/cache/yum; \
{{ ) end -}}
\
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
\
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
chmod -R +rX .; \
chmod 777 logs temp work; \
\
# smoke test
catalina.sh version
{{ ) else ( -}}
COPY --from=tomcat:{{ .version }}-jdk{{ java_version }}-{{ vendor_variant }} $CATALINA_HOME $CATALINA_HOME
RUN set -eux; \
{{ if is_apt then ( -}}
apt-get update; \
xargs -rt apt-get install -y --no-install-recommends < "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt"; \
rm -rf /var/lib/apt/lists/*
{{ ) else ( -}}
xargs -rt yum install -y < "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt"; \
yum clean all; \
rm -rf /var/cache/yum
{{ ) end -}}
{{ ) end -}}
# verify Tomcat Native is working properly
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
200多行,我们不会展开讲解,但是我们可以讲一些关键字
注意,Dockerfile的关键字必须大写!!!attention please
基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是FROM
镜像维护者的姓名和邮件地址
容器构建时需要运行的命令
两种格式:
1.shell格式
2.exec格式
RUN是在docker build时运行
当前容器对外暴露出的端口
指定在创建容器后,终端默认登录进来的工作目录,一个落脚点
指定该镜像以什么样的用户去执行,如果都不指定,默认是root
用在在构建镜像过程中设置环境变量
将宿主机目录下的文件拷贝进镜像且会自动处理url和解压tar压缩包
类似ADD,拷贝文件和目录到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
容器数据卷,用于数据和持久化工作
指定容器启动后的要干的事情
注意:Dockerfile中可以有多个cmd指令,但是只有最后一个生效,cmd会被docker run之后的参数替代
CMD和RUN的对比:CMD是在docker run的时候执行
RUN是在docker build的时候执行
也是用来指定一个容器启动时要运行的命令
类似于CMD,但是该指令不会被docker run后面的命令覆盖,而且这些命令行参数会被当做参数送给ENTRYPOINT指定的程序
优点:在执行docker run的时候可以指定ENTRYPOINT运行所需的参数
注意:Dockerfile中如果存在多个ENTRYPOINT指令,仅最后一个生效
ok,今天的介绍就暂时到这里,谢谢大家的观看,