docker基础总结

鱼渝
2023-12-01

Docker基础使用总结

Author:onceday Date:2022年11月11日

漫漫长路,有人对你微笑过嘛…

1.简介

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。

安装详情参考:

以ubuntu为例,安装步骤如下:

(1) 使用官方脚本手动安装

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

(2) 手动安装

  • 卸载可能已安装过的旧版本

    sudo apt-get remove docker docker-engine docker.io containerd runc
    
  • 当前称为 Docker Engine-Community 软件包 docker-ce 。安装之前需要首先设置Docker仓库。

    sudo apt-get update
    sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common
    
  • 添加 Docker 的官方 GPG 密钥:

    curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
    
  • 设置稳定版仓库(CPU架构根据实际情况决定)

    sudo add-apt-repository \
       "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
      $(lsb_release -cs) \
      stable"
    
  • 先更新apt包索引

    sudo apt-get update
    

完成上面的操作之后,下面就可以正式开始安装docker了

首先可以查看仓库中可用的版本,然后选一种(Docker Engine-Community)安装:

root@ubuntu:test# apt-cache madison docker-ce
 docker-ce | 5:20.10.21~3-0~ubuntu-focal | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.20~3-0~ubuntu-focal | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.19~3-0~ubuntu-focal | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu focal/stable amd64 Packages
.......

然后根据版本号来安装(例如,VERSION_STRING = 5:20.10.21~3-0~ubuntu-focal):

sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io

也可以直接安装最新版本的Docker Engine-Community和containerd。

sudo apt-get install docker-ce docker-ce-cli containerd.io

使用以下命令测试docker是否安装成功。

docker version

卸载docker可以使用下面两步操作

#删除安装包
sudo apt-get purge docker-ce
#删除镜像,容器,配置文件等内容
sudo rm -rf /var/lib/docker

2.docker 镜像加速

可以使用科大镜像:https://docker.mirrors.ustc.edu.cn/

配置文件有/etc/default/docker/etc/docker/daemon.json

对于Ubuntu16.04+、Debian8+、CentOS7以上操作系统,使用/etc/docker/daemon.json,不存在可以新建。

写入以下内容:

{"registry-mirrors":["https://docker.mirrors.ustc.edu.cn/"]}

然后重启docker服务:

sudo systemctl daemon-reload
sudo systemctl restart docker

Windows端,可以直接在Docker桌面应用里设置中添加

使用docker info查看是否设置成功:

root@ubuntu:~# docker info
......省略大量字符......
 Registry Mirrors:
  https://docker.mirrors.ustc.edu.cn/
 Live Restore Enabled: false

WARNING: No swap limit support

3.基础使用

3.1 获取帮助信息

使用任何工具都可以养成使用-h, --help来获取帮助的习惯,毕竟工具那么多,全记住也不可能。

root@ubuntu:~# docker

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and
                           default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  app*        Docker App (Docker Inc., v0.9.1-beta3)
  builder     Manage builds
  buildx*     Docker Buildx (Docker Inc., v0.9.1-docker)
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  scan*       Docker Scan (Docker Inc., v0.21.0)
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

To get more help with docker, check out our guides at https://docs.docker.com/go/guides/
3.2 运行hello world

docke可以在运行容器,然后在容器中执行应用程序。即docker run命令。

root@ubuntu:~# docker run 
"docker run" requires at least 1 argument.
See 'docker run --help'.

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container
root@ubuntu:~# 

可以使用docker run --help获取详细的命令参数信息

root@ubuntu:~# docker run ubuntu:22.04 /bin/echo "Hello world"
Unable to find image 'ubuntu:22.04' locally
22.04: Pulling from library/ubuntu
e96e057aae67: Pull complete 
Digest: sha256:4b1d0c4a2d2aaf63b37111f34eb9fa89fa1bf53dd6e4ca954d47caebca4005c2
Status: Downloaded newer image for ubuntu:22.04
#上面是第一次运行正常的过程
Hello world
  • docker是二进制执行文件。
  • run运行一个新的容器。
  • ubuntu:22.04,指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。需要设置镜像源,否则官方服务器很难连接上去。
  • /bin/echo "Hello world",在启动的容器里执行的命令。

上面的命令实际上以ubuntu:22.04创建了一个新容器,然后在容器里执行bin/echo "hello world",并输出结果。

3.3 交互式运行容器

上面运行的容器有一个缺陷,那就是执行完命令,就无法再继续交互了。

需要使用以下两个参数使得容器具有交互能力。

-i, --interactive                    Keep STDIN open even if not attached
-t, --tty                            Allocate a pseudo-TTY
docker run -i -t ubuntu:22.04 /bin/bash
root@ubuntu:~# docker run -i -t ubuntu:22.04 /bin/bash
root@29cb7072a572:/# cat /proc/version
Linux version 5.4.0-90-generic (buildd@lgw01-amd64-054) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #101-Ubuntu SMP Fri Oct 15 20:00:55 UTC 2021

退出容器很简单,使用exit或者Ctrl+D即可。

3.4 后台运行容器

需要使用run的命令参数:

d, --detach                         Run container in background and print container ID

下面则创建一个以进程方式运行的容器:

root@ubuntu:~# docker run -d ubuntu:22.04 /bin/bash -c "while true; do echo hello world; sleep 1;done"
7c18ed64a0c7412e451c4c660a868b1dc3d95f5e041683eff8d49879b9bb9f3f

其返回的是container ID,即容器ID,对于每个容器都是唯一的。

可以通过docker ps查看容器的运行情况。

root@ubuntu:~# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS  PORTS  NAMES
879df759c0b7   ubuntu:22.04   "/bin/bash -c 'while.."  30 seconds ago  	Up             zen_shannon
7c18ed64a0c7   ubuntu:22.04   "/bin/bash 'while tr…"   6 minutes ago    Exited         naughty_chaplygin
29cb7072a572   ubuntu:22.04   "/bin/bash"              16 minutes ago   Exited         nice_jepsen
c9a8012b1b0c   ubuntu:22.04   "/bin/echo 'Hello wo…"   28 minutes ago   Exited         sweet_ptolemy
55d927df9566   ubuntu:22.04   "/bin/echo 'Hello wo…"   28 minutes ago   Exited         pensive_noyce

大部分字段名就是字面上的意思,不多解释了

PORTS是容器的端口信息,和使用的连接类型tcp/udpNAMES是自动分配的容器名称。

可以使用docker log查看容器输出信息。

#root@ubuntu:~# docker logs zen_shannon
root@ubuntu:~# docker logs 879df759c0b7
hello world
hello world
......

可以使用docker stop命令来停止容器。

root@ubuntu:~# docker stop 879df759c0b7
879df759c0b7

也可以使用docker restart <容器 ID>重启已经停止的容器。

root@ubuntu:~# docker restart 879df759c0b7
879df759c0b7
root@ubuntu:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS PORTS    NAMES
879df759c0b7   ubuntu:22.04   "/bin/bash -c 'while…"   32 minutes ago  Up              zen_shannon

此时可以通过以下两个命令来进入后台模式运行的容器

  • docker attach,挂载stdin,stdout,stderr到一个运行的容器中。

    docker attach 879df759c0b7
    
  • docker exec,在一个运行的容器中执行一个命令。

    docker exec -it 879df759c0b7 /bin/bash
    

    从该命令退出,不会停止运行容器

3.5 获取仓库镜像

使用docker pull可以从远程仓库拉去镜像:

root@ubuntu:~# docker pull --help

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)
      --platform string         Set platform if server is multi-platform capable
  -q, --quiet                   Suppress verbose output

使用docker images查看本地镜像:

root@ubuntu:~# docker images
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
ubuntu-backup   test      4457823ca9de   10 minutes ago   77.8MB
ubuntu          22.04     a8780b506fa4   9 days ago       77.8MB

其中ubuntu是仓库名,Tag是仓库源的不同版本,这里其代表了版本号

查找镜像可以在 Docker Hub 网站来搜索镜像: https://hub.docker.com/

此外也可以使用docker search来搜索镜像:

root@ubuntu:~# docker search ubuntu
NAME                             DESCRIPTION                                     STARS     OFFICIAL  
ubuntu                           Ubuntu is a Debian-based Linux operating sys…   15200     [OK]       
websphere-liberty                WebSphere Liberty multi-architecture images …   290       [OK]       
ubuntu-upstart                   DEPRECATED, as is Upstart (find other proces…   112       [OK]       
neurodebian                      NeuroDebian provides neuroscience research s…   96        [OK]       
......

OFFICIAL表示官方发布的镜像,NAME就是镜像仓库源的名称。

可以使用docker rmidocker image rm移除镜像。

3.6 容器快照

使用docker export命令可以导出本地的某个容器。

root@ubuntu:~# docker export --help
Usage:  docker export [OPTIONS] CONTAINER
Export a container's filesystem as a tar archive
Options:
  -o, --output string   Write to a file, instead of STDOUT
root@ubuntu:~# docker export 879df759c0b7 > test.tar
root@ubuntu:~# ll -h test.tar 
-rw-r--r-- 1 root root 77M Nov 12 22:58 test.tar

使用docker import命令可以导入容器快照为镜像文件。

root@ubuntu:~# docker import --help
Usage:  docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
Import the contents from a tarball to create a filesystem image
Options:
  -c, --change list       Apply Dockerfile instruction to the created image
  -m, --message string    Set commit message for imported image
      --platform string   Set platform if server is multi-platform capable
root@ubuntu:~# docker import ./test.tar ubuntu-backup:test
sha256:4457823ca9def1c87185869840c26462402092b470f4b0b040f5f90ecdd77548
root@ubuntu:~# docker images
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
ubuntu-backup   test      4457823ca9de   16 seconds ago   77.8MB
ubuntu          22.04     a8780b506fa4   9 days ago       77.8MB
3.7 移除容器

删除容器使用docker rm命令。

root@ubuntu:~# docker rm --help
Usage:  docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Options:
  -f, --force     Force the removal of a running container (uses SIGKILL)
  -l, --link      Remove the specified link
  -v, --volumes   Remove anonymous volumes associated with the container
onceday@ubuntu:shell$ docker rm 463c2230e688
463c2230e688

使用docker container prune可以一次性移除所有处于终止状态的容器

移除容器会导致容器类的工作丢失,因此需要做好快照功能,或者确定无用再移除

3.8 创建镜像

创建镜像一般有以下两种方法:

  • 从已经创建的容器中更新镜像,并且提交这个镜像。
  • 使用Dockerfile指令创建一个新的镜像。

对于第一种方法,需要先有一个容器。然后在容器中做出我们希望的更改之后,退出容器,然后使用docker commit来提交容器副本

root@ubuntu:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED        STATUS        PORTS NAMES
879df759c0b7   ubuntu:22.04   "/bin/bash -c 'while…"   13 hours ago   Up 12 hours         zen_shannon
root@ubuntu:~# docker commit -m="a test" -a="onceday" 879df759c0b7 ubuntu-test:v1
sha256:1c45b964dd6640749c6d1ca45be49cbb1a2203de48edf6bdf2cc3438b801f869
root@ubuntu:~# docker images
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
ubuntu-test     v1        1c45b964dd66   10 seconds ago   77.8MB
ubuntu-backup   test      4457823ca9de   12 hours ago     77.8MB
ubuntu          22.04     a8780b506fa4   10 days ago      77.8MB
  • -m,提交的描述信息
  • -a:指定的镜像作者
  • 879df759c0b7 :容器ID
  • ubuntu-test:v1:创建的镜像名和标签。

第二种方法是使用docker build,从零开始创建一个镜像。

root@ubuntu:~# docker build 
"docker build" requires exactly 1 argument.
See 'docker build --help'.
Usage:  docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile

docker build可以指定很多构建镜像的参数,但一般使用下面选项即可。

docker build -t name:tag xxx/Dockerfile

4.Dockerfile构建文件

参考文档:Best practices for writing Dockerfiles | Docker Documentation

Dockerfile是一个用来构建镜像的文本文件,其包含了一条条构建镜像所需的指令和说明。

4.1 from 指定基本镜像

定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

最好不要完全重新创建一个镜像,因为那样会带来额外的启动开销。

一般可以使用官方镜像,选择一个最适合的官方镜像做起来。

#选择基本镜像
FROM ubuntu:22.04
4.2 RUN在构建镜像时执行的命令

有以下两种格式:

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

例如下面的实例:

RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

建议使用&&连接多条指令,因为RUN指令会创建一层新镜像,从而造成镜像体积膨大

这里有个小技巧,和apt-get指令有关。

RUN apt-get update && apt-get install xxxx
#两种方式
RUN apt-get update
RUN apt-get install xxxx

官方推荐使用第一种,第二种方式可能不会去执行apt-get install,因为在之前的步骤已经执行过该命令。所以后续安装的软件包可能是旧版本的。

第一种方式叫缓存破坏(cache busting),所以总会去获取最新的包信息,以确保安装了最新版本。

此外,指定版本号也可以造成缓存破坏,从而去安装最新版本的包。

4.3 上下文路径
docker build -t code-server:lastest .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

4.4 COPY和ADD 复制文件

从上下文目录中复制文件或者目录到容器里指定路径。

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。

对于不需要解压的文件,使用COPY效果更好。

对于COPY需要注意缓存的问题,如下:

COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/

如果您有多个Dockerfile步骤,它们使用来自您的上下文的不同文件,请分别复制它们,而不是一次全部复制。这确保了只有在特定所需的文件更改时,每个步骤的构建缓存才会失效(强制步骤重新运行)。

如果要添加来自网络上的压缩文件, 最好使用RUN+wget+tar来代替,而不是直接使用ADD

ADD https://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
#上面命令不推荐,推荐下面的写法
RUN mkdir -p /usr/src/things \
    && curl -SL https://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all
4.5 CMD 运行容器时执行

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意,如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

4.6 ENTRYPOINT 容器进入点

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意,如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 
  • 不传参运行:docker run nginx:test

    容器内默认执行以下命令:nginx -c /etc/nginx/nginx.conf

  • 传参运行:docker run nginx:test -c /etc/nginx/new.conf

    容器内执行以下命令:nginx -c /etc/nginx/new.conf

4.7 ENV设置环境变量

可以在后续的指令中使用这个环境变量。

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

一个很重要的作用就是添加PATH路径:

ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH
4.8 ARG设置构建参数

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

ARG <参数名>[=<默认值>]
4.9 VOLUME 数据卷

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

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

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

4.10 EXPOSE 声明端口

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

格式:

EXPOSE <端口1> [<端口2>...]
4.11 WORKDIR 指定工作目录

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会建立目录。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR <工作目录路径>

推荐使用绝对路径,这样有助于阅读

实际是为了RUNCMDNTRYPOINTCOPYADD 设置工作目录,就是切换目录

4.12 USER 指定用户和用户组

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

USER <用户名>[:<用户组>]
4.13 HEALTHCHECK 状态监控

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
4.14 ONBUILD 延迟构建指令

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

ONBUILD <其它指令>
4.15 LABLE镜像标签

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...
# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="ACME Incorporated"
LABEL vendor2=ZENITH\ Incorporated

5.Docker 网络端口

要让外部访问Docker的应用,就需要进行端口映射。

映射端口有两种方式:

  • -P :是容器内部端口随机映射到主机的端口。
  • -p : 是容器内部端口绑定到指定的主机端口。
root@ubuntu:~# docker run -d -p 4020:10001 ubuntu:22.04 /bin/bash -c "sleep 1000"
root@ubuntu:~# docker ps -a
CONTAINER ID   IMAGE    ...    PORTS                                         NAMES
35e952931f7e   ubuntu:22.04 0.0.0.0:4020->10001/tcp, :::4020->10001/tcp   ......

也可以绑定到固定的网络地址中:

root@ubuntu:~# docker run -d -p 127.0.0.1:4000:10001 ubuntu:22.04 /bin/bash -c "sleep 1000"
955a9c3164868e556528893c71552d2a13a4410a2580f81d5981d056d3d868e9
root@ubuntu:~# docker ps -a
CONTAINER ID   ...      PORTS                           NAMES
955a9c316486   ...      127.0.0.1:4000->10001/tcp       exciting_lamarr

默认都是绑定 tcp 端口,如果要绑定 UDP 端口,可以在端口后面加上 127.0.0.1:5200/udp

可以使用docker port命令查看端口绑定情况。

root@ubuntu:~# docker port 955a9c316486
10001/tcp -> 127.0.0.1:4000
5.2 创建桥接网络

docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。

docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。

root@ubuntu:~# docker network create -d bridge test-net
1f862d3e78bb576daffdc777b9640410102061f421792077d8e10f61f1a789db
root@ubuntu:~# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
6ed086052ccc   bridge     bridge    local
e9088f9f2e09   host       host      local
fada660960ae   none       null      local
1f862d3e78bb   test-net   bridge    local
  • -d指定Docker网络类型,有bridge/overlay。

然后连接两个容器到新建的test-net网络

root@ubuntu:~# docker run -itd --name once --network test-net ubuntu:22.04 /bin/bash
2d40af68b9d730c665b89e106a4f8d01354cf3275086ed56d6ff8cc0119013f4
root@ubuntu:~# docker run -itd --name day --network test-net ubuntu:22.04 /bin/bash
8a6f62cb9b73098e080824ce0a2fb1748ed2cf875147ea74c0f19532c03739b7
root@ubuntu:~# docker ps
CONTAINER ID   IMAGE           CREATED          STATUS          PORTS     NAMES
8a6f62cb9b73   ubuntu:22.04   4 seconds ago    Up 4 seconds              day
2d40af68b9d7   ubuntu:22.04   11 seconds ago   Up 10 seconds             once
879df759c0b7   ubuntu:22.04   23 hours ago     Up 22 hours               zen_shannon

然后登入其中一个容器,并且安装ping命令:

root@2d40af68b9d7:/# apt-get update 
root@2d40af68b9d7:/# apt-get install iputils-ping
root@2d40af68b9d7:/# ping day
PING day (172.18.0.3) 56(84) bytes of data.
64 bytes from day.test-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from day.test-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.053 ms
64 bytes from day.test-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.070 ms

对于更大数量的容器之间互连,需要使用Docker Compose。

5.3 配置DNS

可以在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS:

{
  "dns" : [
    "114.114.114.114",
    "8.8.8.8"
  ]
}

没有这个文件则需要新建darmon.json

然后重启Docker便可以生效。

docker run -it ubuntu:22.04  cat etc/resolv.conf

也可以对着容器直接指定生成对应的DNS:

docker run -it -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu:22.04
  • -h HOSTNAME/--hostname=HOSTNAME,设定容器的主机名,会被写入到容器内的/etc.hostname/etc/hosts
  • --dns=IP_ADDRESS:添加DNS服务器到容器的/etc/resolv.conf中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
  • --dns-search=DOMAIN设定容器的搜索域,当搜索域为example.com时,在搜索一个名为host的主机时,DNS不仅会搜索host,还会搜索host.example.com

6.Docker Compose

如果总是需要配置复杂的容器运行环境,那么使用docker run是很低效的。

通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。整体逻辑如下:

  • Dockerfile 定义镜像,其包含运行环境。
  • docker-compose.yml 定义镜像运行的参数,组成实际的容器。
  • 执行 docker-compose up 命令便可以运行该容器了。

一个典型的配置如下:

# yaml 配置实例
version: '3'
services:
  web:
    build: .
    ports:
   - "5000:5000"
    volumes:
   - .:/code
    - logvolume01:/var/log
    links:
   - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

Compose一般都默认安装了,详情可参考:Docker Compose | 菜鸟教程 (runoob.com)

6.1 创建工作目录
onceday@ubuntu:shell$ mkdir compose_test
onceday@ubuntu:shell$ cd compose_test/
onceday@ubuntu:compose_test$ 

然后可以创建准备在docker中使用的相关配置文件:

onceday@ubuntu:compose_test$ touch test.py
onceday@ubuntu:compose_test$ touch test.requirements.txt
onceday@ubuntu:compose_test$ ll
total 8
drwxr-xr-x 2 onceday OD 4096 Nov 14 20:52 ./
drwxr-xr-x 3 onceday OD 4096 Nov 14 20:51 ../
-rw-r--r-- 1 onceday OD    0 Nov 14 20:52 test.py
-rw-r--r-- 1 onceday OD    0 Nov 14 20:52 test.requirements.txt

以上只是举例,具体文件需要根据自己的需求来确定

然后可以创建一个docker文件:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
6.2 创建docker-compose.yaml

在工作目录中创建一个docker-compose文件。

# yaml 配置
version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

该Compose文件定义了两个服务

每个服务都是一个指定的镜像,web是从从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。

redis 服务使用 Docker Hub 的公共 Redis 映像。

然后使用compose命令构建和运行程序

docker-compose up [-d]
6.3 一些重要的配置指令
6.3.1 version,指定yaml文件所对应的compose版本。
version: "3.7"
6.3.2 build,指定构建镜像的上下文路径。
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:多层构建,可以指定构建哪一层。
6.3.3 cap_add/cap_drop,添加或删除容器拥有的宿主机的内核功能。
cap_add:
  - ALL # 开启全部权限
cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限
6.3.4 cgroup_parent,为容器指定父 cgroup 组,意味着将继承该组的资源限制。
cgroup_parent: m-executor-abcd
6.3.5 command,覆盖容器启动的默认命令。
command: ["bundle", "exec", "thin", "-p", "3000"]
6.3.6 container_name,指定自定义容器名称,而不是生成的默认名称。
container_name: my-web-container
6.3.7 depends_on,设置依赖关系。
  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres
6.3.8 devices,指定设备映射列表。
devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"
6.3.9 dns,自定义 DNS 服务器,可以是单个值或列表的多个值。
dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9
6.3.10 dns_search,自定义 DNS 搜索域。可以是单个值或列表。
dns_search: example.com

dns_search:
  - dc1.example.com
  - dc2.example.com
6.3.11 entrypoint,覆盖容器默认的 entrypoint。
entrypoint: /code/entrypoint.sh
entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit
6.3.12 env_file,从文件添加环境变量。可以是单个值或列表的多个值。
env_file: .env
env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env
6.3.13 environment,添加环境变量。可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保yaml解析器不会将其转换为 TrueFalse
environment:
  RACK_ENV: development
  SHOW: 'true'
6.3.14 expose,暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数:
expose:
 - "3000"
 - "8000"
6.3.15 extra_hosts,添加主机名映射。类似 docker client --add-host。
extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"
6.3.16 healthcheck,检测 docker 服务是否健康运行。
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序
6.3.17 image,指定容器运行的镜像。以下格式都可以:
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id
6.3.18 logging,服务的日志记录配置。driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项:
driver: "json-file"
driver: "syslog"
driver: "none"
#在json-file驱动程序下,可以使用以下参数,限制日志的数量和大小
logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

当达到文件限制上限,会自动删除旧得文件。syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"
6.3.19 network_mode,设置网络模式。
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
6.3.20 networks,配置容器连接的网络,引用顶级networks下的条目。
services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases,同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。

6.3.21 restart ,重启策略。
  • no:是默认的重启策略,在任何情况下都不会重启容器。
  • always:容器总是重新启动。
  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
6.3.22 secrets存储敏感数据:
version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt
6.3.23 security_opt修改容器默认的schema标签。
security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签
6.3.24 stop_grace_period,如果容器无法处理stop_signal信号,等待多久之后发送SIGKILL信号关闭容器。
stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 

默认的等待时间是10s

6.3.25 stop_signal,设置停止容器的替代信号。默认情况下使用 SIGTERM 。以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器。
stop_signal: SIGUSR1
6.3.26 sysctls,设置容器中的内核参数,可以使用数组或字典格式。
sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0
6.3.27 tmpfs,在容器内安装一个临时文件系统,可以是单个值或列表的多个值。
tmpfs: /run
tmpfs:
  - /run
  - /tmp
6.3.28 ulimits,覆盖容器默认的 ulimit。
ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000
6.3.29 volumes,将主机的数据卷或着文件挂载到容器里。
version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"
 类似资料: