Author:onceday Date:2022年11月11日
漫漫长路,有人对你微笑过嘛…
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
可以使用科大镜像: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
使用任何工具都可以养成使用-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/
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"
,并输出结果。
上面运行的容器有一个缺陷,那就是执行完命令,就无法再继续交互了。
需要使用以下两个参数使得容器具有交互能力。
-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
即可。
需要使用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/udp
。NAMES
是自动分配的容器名称。
可以使用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
从该命令退出,不会停止运行容器。
使用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 rmi
、docker image rm
移除镜像。
使用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
删除容器使用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
可以一次性移除所有处于终止状态的容器。
移除容器会导致容器类的工作丢失,因此需要做好快照功能,或者确定无用再移除。
创建镜像一般有以下两种方法:
对于第一种方法,需要先有一个容器。然后在容器中做出我们希望的更改之后,退出容器,然后使用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
,提交的描述信息879df759c0b7
:容器IDubuntu-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
参考文档:Best practices for writing Dockerfiles | Docker Documentation
Dockerfile
是一个用来构建镜像的文本文件,其包含了一条条构建镜像所需的指令和说明。
定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
最好不要完全重新创建一个镜像,因为那样会带来额外的启动开销。
一般可以使用官方镜像,选择一个最适合的官方镜像做起来。
#选择基本镜像
FROM ubuntu:22.04
有以下两种格式:
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),所以总会去获取最新的包信息,以确保安装了最新版本。
此外,指定版本号也可以造成缓存破坏,从而去安装最新版本的包。
docker build -t code-server:lastest .
上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
从上下文目录中复制文件或者目录到容器里指定路径。
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
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意,如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。
类似于 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
。
可以在后续的指令中使用这个环境变量。
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
一个很重要的作用就是添加PATH
路径:
ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH
构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build
中可以用 --build-arg <参数名>=<值>
来覆盖。
ARG <参数名>[=<默认值>]
定义匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。作用:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
作用:
格式:
EXPOSE <端口1> [<端口2>...]
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会建立目录。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
WORKDIR <工作目录路径>
推荐使用绝对路径,这样有助于阅读。
实际是为了RUN
、CMD
、NTRYPOINT
、COPY
和 ADD
设置工作目录,就是切换目录。
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
USER <用户名>[:<用户组>]
用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build
)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build
,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
ONBUILD <其它指令>
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
要让外部访问Docker的应用,就需要进行端口映射。
映射端口有两种方式:
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
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。
可以在宿主机的 /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
。如果总是需要配置复杂的容器运行环境,那么使用docker run
是很低效的。
通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。整体逻辑如下:
一个典型的配置如下:
# 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)
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"]
在工作目录中创建一个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]
version
,指定yaml文件所对应的compose版本。version: "3.7"
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
cap_add
/cap_drop
,添加或删除容器拥有的宿主机的内核功能。cap_add:
- ALL # 开启全部权限
cap_drop:
- SYS_PTRACE # 关闭 ptrace权限
cgroup_parent
,为容器指定父 cgroup 组,意味着将继承该组的资源限制。cgroup_parent: m-executor-abcd
command
,覆盖容器启动的默认命令。command: ["bundle", "exec", "thin", "-p", "3000"]
container_name
,指定自定义容器名称,而不是生成的默认名称。container_name: my-web-container
depends_on
,设置依赖关系。version: "3.7"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
devices
,指定设备映射列表。devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
dns
,自定义 DNS 服务器,可以是单个值或列表的多个值。dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
dns_search
,自定义 DNS 搜索域。可以是单个值或列表。dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
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
env_file
,从文件添加环境变量。可以是单个值或列表的多个值。env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
environment
,添加环境变量。可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保yaml
解析器不会将其转换为 True
或 False
。environment:
RACK_ENV: development
SHOW: 'true'
expose
,暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数:expose:
- "3000"
- "8000"
extra_hosts
,添加主机名映射。类似 docker client --add-host。extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
healthcheck
,检测 docker 服务是否健康运行。healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
interval: 1m30s # 设置检测间隔
timeout: 10s # 设置检测超时时间
retries: 3 # 设置重试次数
start_period: 40s # 启动后,多少秒开始启动检测程序
image
,指定容器运行的镜像。以下格式都可以:image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id
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"
network_mode
,设置网络模式。network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
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
,同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。
restart
,重启策略。restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
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
security_opt
修改容器默认的schema标签。security-opt:
- label:user:USER # 设置容器的用户标签
- label:role:ROLE # 设置容器的角色标签
- label:type:TYPE # 设置容器的安全策略标签
- label:level:LEVEL # 设置容器的安全等级标签
stop_grace_period
,如果容器无法处理stop_signal
信号,等待多久之后发送SIGKILL信号关闭容器。stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒
默认的等待时间是10s。
stop_signal
,设置停止容器的替代信号。默认情况下使用 SIGTERM 。以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器。stop_signal: SIGUSR1
sysctls
,设置容器中的内核参数,可以使用数组或字典格式。sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
tmpfs
,在容器内安装一个临时文件系统,可以是单个值或列表的多个值。tmpfs: /run
tmpfs:
- /run
- /tmp
ulimits
,覆盖容器默认的 ulimit。ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
volumes
,将主机的数据卷或着文件挂载到容器里。version: "3.7"
services:
db:
image: postgres:latest
volumes:
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
- "/localhost/data:/var/lib/postgresql/data"