Docker-Dockerfile学习

Posted lady_killer9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker-Dockerfile学习相关的知识,希望对你有一定的参考价值。

目录


什么是Dockerfile?

Dockerfile简介

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像时所需命令和容器运行时执行的指令和说明。

指令详解

FROM

构建镜像基于哪个镜像
例如,

FROM alpine:latest

MAINTAINER

镜像维护者姓名或邮箱地址,例如

MAINTAINER lady_killer9

WORKDIR

为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录,没有会自动创建,命令在该目录下执行。进入容器也是进入到此目录。例如,

WORKDIR /app

ADD(不推荐)

拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压

COPY(推荐)

拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能。例如,

COPY src/ /app

RUN

构建镜像时运行的指令,例如

RUN pip install requests

CMD

运行容器时执行的命令,如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
CMD有三种形式

  • CMD [“executable”,“param1”,“param2”] ,json数组
  • CMD command param1 param2,shell形式
  • CMD [“param1”,“param2”] ,作为 ENTRYPOINT的默认参数
    例如,
CMD python3 test.py

注意:CMD命令执行的脚本等需要一直运行,否则创建容器后会很快停止。

ENTRYPOINT

ENTRYPOINT 有两种形式:

  1. ENTRYPOINT [“executable”, “param1”, “param2”] ,json数组
  2. ENTRYPOINT command param1 param2,shell形式
    运行容器时执行,如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
    但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
    优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
    CMD与ENTRYPOINT的情况(官方文档):

博主总结如下:

  • CMD和ENTRYPOINT至少有一个
  • 仅有一个时就按照这个命令
  • 有两个时,ENTRYPOINT不是json数组形式,则以ENTRYPOINT为准
  • 有两个时,若ENTRYPOINT与CMD都是json数组形式,则ENTRYPOINT与CMD拼接成shell形式

USER

为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户,一般不指定为root

EXPOSE

声明容器的服务端口

EXPOSE <port> [<port>/<protocol>...]

例如,

EXPOSE 80
EXPOSE 8080/http

之后run的时候可以配合-p参数映射到宿主机上

ENV

设置容器环境变量

ENV <key>=<value> ...

例如,

ENV JAVA_HOME=/home/myuser/jdk1.7.0_03

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

例如,

VOLUME /var/log/nginx

Docker 命令

之前的文章Docker命令学习已经讲解了部分命令,但是构建等命令没有提及。

docker build

用于使用 Dockerfile 创建镜像。

docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

  • –build-arg=[] :设置镜像创建时的变量;

  • –cpu-shares :设置 cpu 使用权重;

  • –cpu-period :限制 CPU CFS周期;

  • –cpu-quota :限制 CPU CFS配额;

  • –cpuset-cpus :指定使用的CPU id;

  • –cpuset-mems :指定使用的内存 id;

  • –disable-content-trust :忽略校验,默认开启;

  • -f :指定要使用的Dockerfile路径;

  • –force-rm :设置镜像过程中删除中间容器;

  • –isolation :使用容器隔离技术;

  • –label=[] :设置镜像使用的元数据;

  • -m :设置内存最大值;

  • –memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;

  • –no-cache :创建镜像的过程不使用缓存;

  • –pull :尝试去更新镜像的新版本;

  • –quiet, -q :安静模式,成功后只输出镜像 ID;

  • –rm :设置镜像成功后删除中间容器;

  • –shm-size :设置/dev/shm的大小,默认值是64M;

  • –ulimit :Ulimit配置。

  • –squash :将 Dockerfile 中所有的操作压缩为一层。

  • –tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。

  • –network: 默认 default。在构建期间设置RUN指令的网络模式

一般都是把Dockerfile放到项目里面,例如

docker build -t myapp:v1.0 .

docker commit

从容器创建一个新的镜像。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS说明:

  • -a :提交的镜像作者;
  • -c :使用Dockerfile指令来创建镜像;
  • -m :提交时的说明文字;
  • -p :在commit时,将容器暂停。

docker save

将镜像输出到一个文件。

docker save [OPTIONS] IMAGE [IMAGE...]

OPTIONS 说明:

  • -o :输出到的文件。

例如,

docker save -o myapp_v1.0.tar myapp:v1.0

docker load

从一个文件加载镜像

docker load [OPTIONS]

OPTIONS 说明:

  • –input , -i : 指定导入的文件,代替 STDIN。

  • –quiet , -q : 精简输出信息。

例如,

docker load -i myapp_v1.0.tar

Dockerfile举例

mysql debian

#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM debian:buster-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql

RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*

# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; \\
	savedAptMark="$(apt-mark showmanual)"; \\
	apt-get update; \\
	apt-get install -y --no-install-recommends ca-certificates wget; \\
	rm -rf /var/lib/apt/lists/*; \\
	dpkgArch="$(dpkg --print-architecture | awk -F- ' print $NF ')"; \\
	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \\
	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \\
	export GNUPGHOME="$(mktemp -d)"; \\
	gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \\
	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \\
	gpgconf --kill all; \\
	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \\
	apt-mark auto '.*' > /dev/null; \\
	[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \\
	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \\
	chmod +x /usr/local/bin/gosu; \\
	gosu --version; \\
	gosu nobody true

RUN mkdir /docker-entrypoint-initdb.d

RUN set -eux; \\
	apt-get update; \\
	apt-get install -y --no-install-recommends \\
		openssl \\
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
		perl \\
		xz-utils \\
		zstd \\
	; \\
	rm -rf /var/lib/apt/lists/*

RUN set -eux; \\
# gpg: key 3A79BD29: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
	key='859BE8D7C586F538430B19C2467B942D3A79BD29'; \\
	export GNUPGHOME="$(mktemp -d)"; \\
	gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \\
	mkdir -p /etc/apt/keyrings; \\
	gpg --batch --export "$key" > /etc/apt/keyrings/mysql.gpg; \\
	gpgconf --kill all; \\
	rm -rf "$GNUPGHOME"

ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.37-1debian10

RUN echo 'deb [ signed-by=/etc/apt/keyrings/mysql.gpg ] http://repo.mysql.com/apt/debian/ buster mysql-5.7' > /etc/apt/sources.list.d/mysql.list

# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN  \\
		echo mysql-community-server mysql-community-server/data-dir select ''; \\
		echo mysql-community-server mysql-community-server/root-pass password ''; \\
		echo mysql-community-server mysql-community-server/re-root-pass password ''; \\
		echo mysql-community-server mysql-community-server/remove-test-db select false; \\
	 | debconf-set-selections \\
	&& apt-get update \\
	&& apt-get install -y \\
		mysql-server="$MYSQL_VERSION" \\
# comment out a few problematic configuration values
	&& find /etc/mysql/ -name '*.cnf' -print0 \\
		| xargs -0 grep -lZE '^(bind-address|log)' \\
		| xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \\
# don't reverse lookup hostnames, they are usually another container
	&& echo '[mysqld]\\nskip-host-cache\\nskip-name-resolve' > /etc/mysql/conf.d/docker.cnf \\
	&& rm -rf /var/lib/apt/lists/* \\
	&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \\
	&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \\
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
	&& chmod 1777 /var/run/mysqld /var/lib/mysql

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

这是mysql的官方Dockerfile,基于debian:buster-slim镜像,执行了一些命令,添加了环境变量GOSU_VERSION、MYSQL_VERSION 等,添加了匿名挂载卷/var/lib/mysql,复制了docker-entrypoint.sh脚本到 /usr/local/bin/下,运行脚本,暴露端口3306和33060。

参考

菜鸟教程-Docker Dockerfile
Docker如何制作镜像-Dockerfile的使用
docker官方文档-docker命令
docker官方文档-dockerfile
Github-mysql-5.7-dockerfile-debian

以上是关于Docker-Dockerfile学习的主要内容,如果未能解决你的问题,请参考以下文章

Docker-dockerfile

docker-Dockerfile 创建镜像

Docker-Dockerfile格式

docker-dockerfile

Docker-Dockerfile1

Docker-dockerfile文件