Docker目前支持Centos7及以后的版本。64位操作系统,内核版本至少为3.10
安装软件源,以及devicemapper存储类型
[root@docker ~]# yum update -y
[root@docker ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
添加Docker yum源
[root@docker ~]# yum-config-manager --add-repo \
> https://download.docker.com/linux/centos/docker-ce.repo
安装Docker
[root@docker ~]# yum install -y docker-ce
启动Docker
[root@docker ~]# systemctl enable docker --now
测试是否能获取镜像
[root@docker ~]# docker run hello-world
查看获取的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://9dkjece7.mirror.aliyuncs.com"]
}
EOF
生效配置信息
systemctl daemon-reload && systemctl restart docker
安装Docker需要保证你的电脑开启虚拟化
进入任务管理器→点击性能→看一下CPU是否开启虚拟化
启用Hyper-v
打开控制面板→程序→启动或关闭Windows功能→找到Hyper-V打上√
下载地址:https://www.docker.com/products/docker-desktop/
如果打开后提升启动出现问题,需要安装wsl内核更新包wsl_update_x64
下载完后双击安装即可
Docker的版本
拉取镜像
运行拉取的镜像
设置暴露的端口,和容器名
默认官方源因为网络原因比较慢,我们使用阿里云的镜像源
自己注册一个阿里云,搜索容器镜像服务→镜像工具→镜像加速器,即可获取加速地址,然后填入如下内容框即可。
Docker运行容器前需要存在对应的镜像,如果镜像不存在,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub仓库),用户也可以通过配置,使用自定义的镜像仓库。
官方的Docker Hub网站已经提供了数十万个镜像供大家下载,只需要使用pull命令,既可以拉取Docker Hub中的镜像。
docker [image] pull
命令直接从Docker Hub 镜像源来下载镜像。该命令格式为docker [image] pull
pull子命令主要包括有:
例如,获取一个Ubuntu 18.04 系统的基础镜像可以使用如下命令
[root@docker ~]# docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
284055322776: Pull complete
Digest: sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04
# 如果不指定TAG,则默认会选择latest标签,下载最新版本的镜像
例如,从Docker Hub的Ubuntu仓库下载一个最新版本的Ubuntu操作系统的镜像
[root@docker ~]# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
# 该命令实际下载的是ubuntu:latest镜像
在不同的仓库中服务器的情况下,可能会出现镜像重名情况,镜像的仓库名称中还应该添加仓库地址作为前缀,至是docker默认使用的是官方Docker Hub镜像仓库,前缀可以忽略。
docker pull ubuntu:18.04
就相当于docker.io/library/ubuntu:18.04
命令,即从Docker Hub 中的Ubuntu仓库来下载标签为18.04的镜像。
例如,从Docker Hub中的mysql仓库中拉取mysql5.7镜像
[root@docker ~]# docker pull docker.io/library/mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
如果从非官方仓库下载,则需要在仓库名称前指定完整的仓库地址
使用docker images
或者 docker image ls
命令可以列出本地主机上已有镜像
docker images 子命令主要包括:
例如,列出上一小节所获取的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
mysql 5.7 c20987f18b13 19 months ago 448 MB
ubuntu latest ba6acccedd29 22 months ago 72.8MB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
在列出的信息中,可以看到几个字段信息,我们从做到右依次解释
REPOSITORY
:来自于那个仓库TAG
:镜像的标签信息IMAGE ID
:镜像的ID,如果两个镜像的ID相同,说明它们实际上指向了同一个镜像,只是具有不同标签名称而已CREATED
:创建的时间SIZE
:镜像大小为了使用特定的镜像,还可以使用docker tag
命令来为本地镜像任意添加新的标签。
例如,添加一个新的myubuntu:latest镜像标签
[root@docker ~]# docker tag ubuntu:latest myubuntu:latest
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
mysql 5.7 c20987f18b13 19 months ago 448 MB
myubuntu latest ba6acccedd29 22 months ago 72.8MB
ubuntu latest ba6acccedd29 22 months ago 72.8MB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
# 可以看到myubuntu:latest和ubuntu:latest ID是完全一致的
# 它们实际上指向了同一个镜像文件,只是别名不同而已,类似Linux硬链接
以后用户,就可以直接使用myubuntu:latest来表示这个镜像
使用docker [image] inspect
命令可以获取镜像的详细信息
docker inspect 子命令主要包括:
例如,查看ubuntu:18.04镜像的详细信息
[root@docker ~]# docker inspect ubuntu:18.04
[
{
"Id": "sha256:5a214d77f5d747e6ed81632310baa6190301feeb875cf6bf9da560108fa09972",
"RepoTags": [
"ubuntu:18.04"
],
"RepoDigests": [
"ubuntu@sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6"
],
"Parent": "",
"Comment": "",
"Created": "2021-10-01T02:23:24.179667784Z",
"Container": "20d614d2eca1b5a9ad6d5a56a80efce44096b87ca76a98256eb51f8dbaf7a8d2",
"ContainerConfig": {
"Hostname": "20d614d2eca1",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"bash\"]"
],
"Image": "sha256:de5a48194cb6a383c018b7c57fa642457688605c5d6d4941db88fecabd225a55",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"bash"
],
"Image": "sha256:de5a48194cb6a383c018b7c57fa642457688605c5d6d4941db88fecabd225a55",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 63136384,
"VirtualSize": 63136384,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/merged",
"UpperDir": "/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/diff",
"WorkDir": "/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:824bf068fd3dc3ad967022f187d85250eb052f61fe158486b2df4e002f6f984e"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
上面的代码返回是一个JSON的格式信息,如果我们只要其中一项内容,可以使用 -f来指定
例如,获取镜像的GraphDriver
[root@docker ~]# docker inspect -f {{".GraphDriver"}} ubuntu:18.04
{map[MergedDir:/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/merged UpperDir:/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/diff WorkDir:/var/lib/docker/overlay2/b6c556d3b654fcb31246d7be3c91504fb0a94a23a5dc843275ce0bc7108fcd84/work] overlay2}
docker history
该命令就是查看镜像各层的创建信息
docker history 子命令主要包括:
例如,查看ubuntu:18.04镜像的创建过程
[root@docker ~]# docker history ubuntu:18.04
IMAGE CREATED CREATED BY SIZE COMMENT
5a214d77f5d7 22 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 22 months ago /bin/sh -c #(nop) ADD file:0d82cd095966e8ee7… 63.1MB
使用docker search
命令可以搜索 Docker Hub官方仓库中的镜像。
docker search子命令主要包括:
例如,搜索官方提供的带nginx关键字的镜像
[root@docker ~]# docker search --filter="is-official=true" nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 18861 [OK]
unit Official build of NGINX Unit: Universal Web … 8 [OK]
# --filter="is-official=true" :仅显示官方镜像
例如搜索收藏超过150的nginx镜像
[root@docker ~]# docker search --filter=stars=150 nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 18861 [OK]
bitnami/nginx Bitnami nginx Docker Image 171 [OK]
使用docker rmi
或docker image rm
命令可以删除镜像
docker rmi 支持的子命令包括:
例如,要删掉myubuntu:latest镜像,使用如下命令
[root@docker ~]# docker rmi myubuntu:latest
Untagged: myubuntu:latest
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
mysql 5.7 c20987f18b13 19 months ago 448 MB
ubuntu latest ba6acccedd29 22 months ago 72.8MB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
例如,再次删除ubuntu:latest 镜像
[root@docker ~]# docker rmi ubuntu:latest
Untagged: ubuntu:latest
Deleted: sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1
Deleted: sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b
# 用该命令删除只有一个标签的镜像
# 就会删除这个镜像文件的所有文件层
当使用docker rmi
命令,后面可以跟上镜像的ID,会先尝试删除所有指向该镜像的标签,然后删除该镜像文件本身
[root@docker ~]# docker tag ubuntu:18.04 ubuntu1:18.04
[root@docker ~]# docker tag ubuntu:18.04 ubuntu2:18.04
[root@docker ~]# docker tag ubuntu:18.04 ubuntu3:18.04
[root@docker ~]# docker tag ubuntu:18.04 ubuntu4:18.04
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu2 18.04 5a214d77f5d7 22 months ago 63.1MB
ubuntu3 18.04 5a214d77f5d7 22 months ago 63.1MB
ubuntu4 18.04 5a214d77f5d7 22 months ago 63.1MB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
ubuntu1 18.04 5a214d77f5d7 22 months ago 63.1MB
[root@docker ~]# docker rmi -f 5a214d77f5d7
Untagged: ubuntu1:18.04
Untagged: ubuntu2:18.04
Untagged: ubuntu3:18.04
Untagged: ubuntu4:18.04
Untagged: ubuntu:18.04
Untagged: ubuntu@sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6
Deleted: sha256:5a214d77f5d747e6ed81632310baa6190301feeb875cf6bf9da560108fa09972
Deleted: sha256:824bf068fd3dc3ad967022f187d85250eb052f61fe158486b2df4e002f6f984e
使用Docker一段时间后,系统可能会遗留一些临时镜像,以及一些没有被使用的镜像,可以通过 docker image prune
命令来进行清理
子命令包括:
例如,如下命令会自动清理临时遗留镜像文件层,最后会提示释放的存储空间
[root@docker ~]# docker image prune -f
Total reclaimed space: 0B
创建镜像的方法主要有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建
使用docker [container] commit
命令
子命令主要包括:
首先,启动一个镜像,并在其中进行修改操作。例如,创建一个test文件
[root@docker ~]# docker run -it ubuntu:18.04 /bin/bash
Unable to find image 'ubuntu:18.04' locally
18.04: Pulling from library/ubuntu
284055322776: Pull complete
Digest: sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6
Status: Downloaded newer image for ubuntu:18.04
root@aaf6fb3716c2:/# touch test
root@aaf6fb3716c2:/# exit
此时该容器与原ubuntu:18.04镜像相比,已经发生改变,可以使用docker [container] commit
命令来提交一个新的镜像。提交时可以使用ID或者名称来指定容器:
[root@docker ~]# docker commit -m "ADD a new file" -a "csq" aaf6fb3716c2 ubuntu-test:v1.0
sha256:1c4941a71868441ccf5a2d48ec0aca6d7849dbea59f792641b63136af49d45b0
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-test v1.0 1c4941a71868 9 seconds ago 63.1MB
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
用户也可以直接从一个操作系统模板文件导入一个镜像,主要使用docker [container] import 命令。命令格式为 docker import [OPTIONS] file URL - [REPOSITORY[:TAG]]
[root@docker ~]# cat ubuntu:test2 | docker import - ubuntu:test2
sha256:8fa21f2c23a05b4186cf3c202aaafc0867d3de85eaf48b1570db5470d2dc2dfb
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu test2 8fa21f2c23a0 5 seconds ago 63.1MB
ubuntu-test v1.0 1c4941a71868 About an hour ago 63.1MB
hello-world latest 9c7a54a9a43c 3 months ago 13.3kB
ubuntu 18.04 5a214d77f5d7 22 months ago 63.1MB
Dockerfile创建镜像是最常见的方式,Dockerfile是一个文本文件,利用给定的指令描述基于某个父镜像创建新镜像的过程。
下面给出一个Dockerfile搭建http web服务器简单案例
# 描述镜像
[root@docker ~]# vim Dockerfile-web
FROM centos:centos7.9.2009
RUN yum install -y httpd
WORKDIR /etc/httpd/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
# 构建镜像
[root@docker ~]# docker build -t docker-web:v1.0 -f Dockerfile-web .
# 查看镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-web v1.0 028ec448be69 27 minutes ago 455MB
# 创建挂载目录
[root@docker ~]# mkdir /html
# 运行容器
[root@docker ~]# docker run -d -p 8888:80 -v /html:/var/www/html/ --name docker-web-app docker-web:v1.0
cb49d095761961f36549fea5a76b5ba3d4a7355983eb5dce2f2717c9b04566bb
# 写入html文件
[root@docker ~]# echo "Hello Docker!" > /html/index.html
如果要到处镜像到本地文件,可以使用docker [image] save
命令。到处镜像到指定文件中
例如,到处本地的ubuntu:18.04镜像为文件ubuntu_18.04.tar
[root@docker ~]# docker save -o ubuntu_18.04.tar ubuntu:18.04
[root@docker ~]# ls
anaconda-ks.cfg Dockerfile-web ubuntu_18.04.tar
# -o:写入文件
# 之后用户就可以通过复制ubuntu_18.04.tar 文件将该镜像分享给其他人
可以使用docker [image] load
将导出的tar文件再导入到本地镜像库。
例如,从文件ubuntu_18.04.tar 导入镜像到本地镜像列表
[root@docker ~]# docker rmi -f ubuntu:18.04
Untagged: ubuntu:18.04
Untagged: ubuntu@sha256:0fedbd5bd9fb72089c7bbca476949e10593cebed9b1fb9edf5b79dbbacddd7d6
Deleted: sha256:5a214d77f5d747e6ed81632310baa6190301feeb875cf6bf9da560108fa09972
[root@docker ~]# docker load -i ubuntu_18.04.tar
Loaded image: ubuntu:18.04
# 这将导入镜像及其相关的元数据信息
# 可以使用docker images查看和原镜像一致
# docker load -i ubuntu_18.04.tar
# 或者 docker load < ubuntu_18.04.tar
# 都是可以的
可以使用docker [image] push
命令上传镜像到仓库,默认上传到Docker Hub 官方仓库(需要登录
)。
我们这里使用阿里云仓库上传镜像
例如,用户csq上传本地的docker-web:v1.0 镜像到阿里云仓库,可以先添加新标签,登录阿里云镜像仓库,然后再上传
[root@docker ~]# docker tag 028ec448be69 registry.cn-hangzhou.aliyuncs.com/chenshiren/web:v1.0
[root@docker ~]# docker login --username=csqcsqcsq registry.cn-hangzhou.aliyuncs.com
[root@docker ~]# docker push registry.cn-hangzhou.aliyuncs.com/chenshiren/web:v1.0
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/chenshiren/web]
5f70bf18a086: Pushed
63210fa3cfd0: Pushed
174f56854903: Pushed
v1.0: digest: sha256:7bc1a7b7f3ab7d91cf5f65e88a5ed3d4d62bb031e08ccd9d5cbeeb1652feb2ee size: 948
第一次上传,会提示输入登录信息,之后登录信息会记录到本地
~/.docker
目录下
容器可以看作是镜像的一个实例,它包含了镜像的所有内容以及运行时需要的可写文件层。镜像是一个静态的只读文件,类似于一个应用程序的安装包,而容器则是在镜像的基础上创建的一个可运行的实例。在容器中,我们可以启动、停止、暂停、删除应用程序,并且容器中的应用程序处于运行状态,可以接收请求并与其他容器或主机进行通信。容器的隔离性使得应用程序之间相互独立,互不影响,同时容器的快速启动和高效利用资源的特点使得应用程序的部署和管理更加方便和高效。
可以使用docker [container] create
命令新建一个容器,例如:
[root@docker ~]# docker create -it ubuntu:latest
48fca1d476661321127becb4c9ffac717f8715e05180326da8a0f14b22dca7b2
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48fca1d47666 ubuntu:latest "bash" 5 seconds ago Created vigilant_jemison
使用docker [container] create
命令新建的容器处于停止状态
,可以使用docker [container] start
命令来启动它
[root@docker ~]# docker start 48fca1d47666
48fca1d47666
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48fca1d47666 ubuntu:latest "bash" 4 minutes ago Up 4 seconds vigilant_jemison
除了创建容器后通过start命令来启动,也可以直接新建并启动容器
使用docker [container] run
等价于先执行docker [container] create
命令,再执行docker [container] start
命令
例如,下面命令输出一个hello world,之后容器自动停止
[root@docker ~]# docker run ubuntu:latest /bin/echo 'Hello world!'
Hello world!
[root@docker ~]# docker ps -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b97e34231055 ubuntu:latest "/bin/echo 'Hello wo…" About a minute ago Exited (0) About a minute ago loving_feistel
当你在使用docker [container] run
来创建并启动容器时,Docker后台运行标准操作包括:
检查本地是否存在指定镜像,不存在就在默认仓库拉取镜像
利用镜像创建一个容器,并启动该容器
分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层
从宿主机配置的网桥接口中桥接一个虚拟接口到容器中去
执行用户指定的应用程序
执行完毕后容器自动终止
下面启动一个bash终端,允许用户进行交互
[root@docker ~]# docker run -it ubuntu:18.04 /bin/bash
root@0fbed2a107dd:/#
通过创建的终端输入命令,例如:
root@e10b1baf5df8:/# pwd
/
root@e10b1baf5df8:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@e10b1baf5df8:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:25 pts/0 00:00:00 /bin/bash
root 12 1 0 01:25 pts/0 00:00:00 ps -ef
# 可以看到进程只有/bin/bash应用,没有其他无关的进程
root@e10b1baf5df8:/# exit
# exit退出容器或者ctrl + d 也可以退出容器
可以使用docker container wait CONTAINER [CONTAINER…]子命令来等待容器退出,并打印退出返回结果
某些适合,执行docker [container] run时候因为命令无法正常执行容器会出错 直接退出,此时可以查看退出的错误代码
例如,运行一个ubuntu:18.04容器,并在容器中执行 abc命令
[root@docker ~]# docker run ubuntu:18.04 /bin/abc
[root@docker ~]# docker ps -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b91f848ec405 ubuntu:18.04 "/bin/abc" 4 seconds ago Created hopeful_matsumoto
[root@docker ~]# docker container wait b91f848ec405
127
# 返回错误代码127,表示容器内命令无法找到
# 利用这个方法可以快速定位错误
获取容器的输出信息,可以通过docker [container] logs
命令
子命令主要包括:
例如查看之前运行hello world的容器输出信息
[root@docker ~]# docker logs b97e34231055
hello world
使用docker [container] pause CONTAINER [CONTAINER....]
命令来暂停运行中的容器
先启动一个容器,并将其暂停
# 先开启一个终端,输入如下命令
[root@docker ~]# docker run -it --rm --name test ubuntu:latest /bin/bash
root@8c5a7b756e87:/#
# 使用另一个终端输入命令暂停启动的容器
[root@docker ~]# docker pause test
test
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c5a7b756e87 ubuntu:latest "bash" 32 seconds ago Up 32 seconds (Paused) test
处于paused状态的容器,可以使用docker [container] unpause CONTAINER [CONTAINER...]
命令来恢复运行状态
[root@docker ~]# docker unpause test
test
使用docker [container] stop
来终止一个运行中的容器
例如终止刚刚启动的test容器
[root@docker ~]# docker stop test
可以使用docker container prune 命令,自动清除处于停止状态的容器
[root@docker ~]# docker container prune -f
Total reclaimed space: 1.629kB
还可以通过docker [container] kill
直接发送SIGKILL
信号来强行终止容器
使用docker [container] restart 命令将会将一个运行状态的容器先终止,然后再重新启动
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d59d5a37d80e ubuntu:latest "/bin/bash" 8 seconds ago Up 7 seconds test
[root@docker ~]# docker restart test
test
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d59d5a37d80e ubuntu:latest "/bin/bash" 31 seconds ago Up 2 seconds test
docker [container] attach [container]
例如,运行一个容器,使用attach进入容器
[root@docker ~]# docker run -itd ubuntu:latest
e48bb01cb3afa88bf7557333129699dc527e5961a398aa78a64165de6b3835cb
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d59d5a37d80e ubuntu:latest "/bin/bash" 3 seconds ago Up 2 seconds dazzling_gould
[root@docker ~]# docker attach d59d5a37d80e
root@d59d5a37d80e:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:07 pts/0 00:00:00 /bin/bash
root 18 1 0 02:22 pts/0 00:00:00 ps -ef
attach命令缺点就是,当多个窗口同时attach到同一个容器中,所有窗口都会同步显示输出命令的信息,当某个窗口因为某些命令阻塞时,其他窗口就无法执行操作了。
docker exec CONTAINER COMMAND [ARG...]
例如,进入刚运行的容器中,并启动一个bash
[root@docker ~]# docker exec -it d59d5a37d80e /bin/bash
root@d59d5a37d80e:/#
root@d59d5a37d80e:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:07 pts/0 00:00:00 /bin/bash
root 9 0 0 02:21 pts/1 00:00:00 /bin/bash
root 17 9 0 02:21 pts/1 00:00:00 ps -ef
可以看到打开了一个新的bash终端,不影响容器内其他应用的前提下,用户可以与容器进行交互
使用docker [container] rm
命令来删除处于终止或退出状态的容器
主要的命令包括:
例如,查看处于终止状态的容器,并删除
[root@docker ~]# docker rm -a
[root@docker ~]# docker rm <目标容器ID>
默认情况下,docker rm只能删除已经终止或退出状态的容器,并不能删除处于运行状态的容器,如果要删除处于运行状态的容器,可以添加-f参数,如下操作
[root@docker ~]# docker run -itd ubuntu
ab937cb8331dadbe3c876d244d4852aefd9fd6dff8c000a54a821eeb6e517db8
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab937cb8331d ubuntu "bash" 2 seconds ago Up 1 second exciting_dijkstra
[root@docker ~]# docker rm -f ab937cb8331d
ab937cb8331d
导出容器是指,导出一个已经创建的容器到一个文具,不管此时这个容器是否处于运行状态。可以使用docker [container] export
命令
例如,查看所有的容器,如下所示
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e817f50ba8f 5a214d77f5d7 "bash" 28 seconds ago Exited (0) 4 seconds ago vigilant_feynman
c5479cddfa41 ba6acccedd29 "bash" 33 seconds ago Up 32 seconds competent_poitras
b1ce6d087e28 028ec448be69 "/usr/sbin/httpd -D …" 39 seconds ago Up 38 seconds 80/tcp determined_sanderson
分别导出9e817f50ba8f容器和b1ce6d087e28容器到文件 ubuntu-stop_container.tar和centos-run_container.tar文件
[root@docker ~]# docker export -o ubuntu-stop_container.tar 9e817f50b
[root@docker ~]# docker export -o centos-run_container.tar b1ce6d087e28
[root@docker ~]# ls
centos-run_container.tar ubuntu-stop_container.tar
使用docker [container] import
命令导入变成镜像
例如,将导出的 centos-run_container.tar 文件导入到系统中
[root@docker ~]# cat centos-run_container.tar | docker import - web:v1.0
sha256:29e91876f87cb5f4b598784687fe2ce44284364290c965ab134b3c92e6ef18b0
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
web v1.0 29e91876f87c 4 seconds ago 430MB
如果需要导入整个镜像,包含镜像的完整文件系统、元数据和历史记录,则使用 docker load
命令。
如果只需要导入容器的文件系统不包含容器的元数据和历史记录,则使用 docker import
命令。
使用 docker inspect NAME|ID [NAME|ID...]
可以查看容器详情
例如,查看某容器的具体信息,容器ID,创建时间,路径,状态,镜像,配置,挂载的卷,IP地址等
[root@docker ~]# docker inspect c5479cddfa41
[
{
"Id": "c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799",
"Created": "2023-08-12T03:05:23.441407028Z",
"Path": "bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 23626,
"ExitCode": 0,
"Error": "",
"StartedAt": "2023-08-12T03:05:23.816138674Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1",
"ResolvConfPath": "/var/lib/docker/containers/c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799/hostname",
"HostsPath": "/var/lib/docker/containers/c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799/hosts",
"LogPath": "/var/lib/docker/containers/c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799/c5479cddfa4182b28015fad7772c7ef30a6a3692a3a77148cdb4c599aeb0e799-json.log",
"Name": "/competent_poitras",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"ConsoleSize": [
30,
152
],
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": [],
"BlkioDeviceWriteBps": [],
"BlkioDeviceReadIOps": [],
"BlkioDeviceWriteIOps": [],
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/44c4df679460426fd1938076820d29ac7f649784bbb11770289d72ccd2ea0c31-init/diff:/var/lib/docker/overlay2/32391dd87dd7516ebd871efa8f8ae1b090cf72be96b7203735325a1aebfa041f/diff",
"MergedDir": "/var/lib/docker/overlay2/44c4df679460426fd1938076820d29ac7f649784bbb11770289d72ccd2ea0c31/merged",
"UpperDir": "/var/lib/docker/overlay2/44c4df679460426fd1938076820d29ac7f649784bbb11770289d72ccd2ea0c31/diff",
"WorkDir": "/var/lib/docker/overlay2/44c4df679460426fd1938076820d29ac7f649784bbb11770289d72ccd2ea0c31/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "c5479cddfa41",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": true,
"OpenStdin": true,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"bash"
],
"Image": "ba6acccedd29",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "e63d385c0b5c932999669bfbd4159a8f41c88e4943b49619acddef348b0b9f35",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/e63d385c0b5c",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "0878c98717d63d3dcf30330b9210c294b517721b3617cf8dc9c0140a500b61c8",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "16c67f25a6a3d844e2454f57cee047d06c02d519b6ab7c69a8b2008dbf3e2690",
"EndpointID": "0878c98717d63d3dcf30330b9210c294b517721b3617cf8dc9c0140a500b61c8",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
查看统计信息可以使用docker [container] stats [CONTAINER...]
命令,会显示CPU、内存、存储、网络等使用情况的统计信息
例如,查看当前运行中容器的系统资源使用统计
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5479cddfa41 ba6acccedd29 "bash" 34 minutes ago Up 34 minutes competent_poitras
[root@docker ~]# docker stats c5479cddfa41
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c5479cddfa41 competent_poitras 0.00% 540KiB / 7.62GiB 0.01% 656B / 0B 0B / 0B 1
使用docker top CONTAINER [ps OPTIONS]
查看容器内进程
该命令会打印出容器内的进程信息,包括PID、用户、时间、命令等
例如查看web容器内的进程信息
[root@docker ~]# docker top web
UID PID PPID C STIME TTY TIME CMD
root 21336 21315 0 12:01 pts/0 00:00:00 /bin/bash
docker [container] cp
命令可以在容器和主机之间复制文件
子命令主要包括:
-a:复制文件会带有原始uid/gid信息
-L:跟随软连接,使用该项会复制链接的目标内容
例如,将本地的路径data复制到web容器的/tmp路径下
[root@docker ~]# docker cp /html web:/tmp/
Successfully copied 2.56kB to web:/tmp/
[root@docker ~]# docker attach web
[root@d12751ef84a4 /]# ls /tmp/
html ks-script-DrRL8A yum.log
例如,将容器内的/tmp目录复制到本地/opt目录下
[root@docker ~]# docker cp web:/tmp /opt
Successfully copied 7.68kB to /opt
[root@docker ~]# ls /opt/tmp/
html ks-script-DrRL8A yum.log
docker [container] diff
查看容器内文件系统的变更
例如,查看web容器内的数据修改
[root@docker ~]# docker diff web
C /tmp
A /tmp/html
A /tmp/html/index.html
输出的每一行都以一个字符开头,表示不同类型的变化:
A
:表示新增的文件或目录C
:表示改变了文件或目录的权限或属性D
:表示删除的文件或目录使用docker [container] port
命令可以查看容器的端口映射情况
例如,查看web容器的端口映射情况
[root@docker ~]# docker port web
80/tcp -> 0.0.0.0:9999
80/tcp -> [::]:9999
使用docker [container] update
可以更新容器的一些运行时配置,它可以更改容器的资源限制、网络设置、重启策略等。
docker update
命令可以接受多个选项来更新容器的不同配置。以下是一些常用的选项:
--blkio-weight
: 设置IO限制,10~1000,默认值为0,代表无限制
--cpu-period
: 设置CPU周期限制
--cpu-quota
: 设置CPU配额限制
--cpu-rt-period
: 设置实时CPU周期限制
--cpu-rt-runtime
: 设置实时CPU运行时间限制
--cpu-shares
, -c
: 设置容器的CPU份额
--cpus
: 设置容器可以使用的CPU数量
--cpuset-cpus
: 设置容器可以使用的CPU核,如0-3,0,1;
--cpuset-mems
: 设置容器可以使用的内存块,如0-3,0,1;
--kernel-memory
: 设置容器的内核内存限制
--memory
, -m
: 设置容器的内存限制
--memory-reservation
: 设置容器的内存保留限制
--memory-swap
: 设置容器的内存+交换限制,-1表示对缓冲区无限制
--restart
:容器退出后的重启策略
no
:默认策略,表示容器退出后不会自动重启。on-failure
:表示只在容器以非零状态退出时才重启。on-failure:3
:在容器非正常退出时重启容器,最多重启3次always
:无论容器以什么状态退出,Docker引擎都会自动重新启动容器。例如,设置web容器的CPU数量为2,重启策略为always
[root@docker ~]# docker update --cpus 2 --restart=always web
查看是否设置成功
[root@docker ~]# docker inspect c6cf5e2be0dc |grep always
"Name": "always",
[root@docker ~]# docker inspect c6cf5e2be0dc |grep -i cpu
"NanoCpus": 2000000000,
选项 | 说明 |
---|---|
-a | 是否绑定到标准输入、输出和错误 |
-d | 是否在后台运行容器, |
-i | 保持标准输入打开 |
-P | 通过NAT机制将容器标记暴露的端口自动映射到本地主机的临时端口下 |
-p | 指定如何映射到本地主机端口,例如 -p 1111-2222:1234-2234 |
–rm | 容器退出后是否自动删除,不能与-d一起使用 |
-t | 是否分配一个伪终端 |
-tmpfs=[ ] | 挂载临时文件系统到容器 |
-w | 容器的默认工作目录 |
-v | 挂载主机上的文件卷到容器内 |
–volumes-from=[ ] | 从其他容器挂载卷 |
–group-add=[ ] | 运行容器的用户组 |
–expose=[ ] | 指定容器会暴露出来的端口或端口范围 |
–restart=[ ] | 容器的重启策略,包括no、no-failure、always、unless-stopped |
–net=[ ] | 指定网络模式 |
选项 | 说明 |
---|---|
-e | 指定容器内的环境变量 |
–link [name:alias] | 链接到其他容器 |
–name | 指定容器别名 |
可以通过官方提供的registry镜像来搭建一套本地私有仓库环境
(1)首先下载registry镜像
[root@docker ~]# docker pull registry:2
2: Pulling from library/registry
79e9f2f55bf5: Pull complete
0d96da54f60b: Pull complete
5b27040df4a2: Pull complete
e2ead8259a04: Pull complete
3790aef225b9: Pull complete
Digest: sha256:169211e20e2f2d5d115674681eb79d21a217b296b43374b8e39f97fcf866b375
Status: Downloaded newer image for registry:2
docker.io/library/registry:2
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry 2 b8604a3fe854 21 months ago 26.2MB
(2)daemon.json文件中添加私有镜像仓库地址
[root@docker ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://9dkjece7.mirror.aliyuncs.com"], # 别忘了逗号
"insecure-registries": ["192.168.200.10:5000"] # 添加这一行
}
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker
(3)运行registry容器
[root@docker ~]# docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry --name registry --restart=always registry:2
c048822be2f277b20f9e17cc2ee7c5ff987acdd0114b5131e1e3fb6322ec44ef
(4)为镜像打上标签
[root@docker ~]# docker tag centos:7.9.2009 192.168.200.10:5000/centos:v1.0
[root@docker ~]# docker push 192.168.200.10:5000/centos:v1.0
The push refers to repository [192.168.200.10:5000/centos]
174f56854903: Pushed
v1.0: digest: sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f size: 529
(5)列出私有仓库所有镜像
[root@docker ~]# curl http://192.168.200.10:5000/v2/_catalog
{"repositories":["centos"]}
(6)列出私有仓库的centos镜像有哪些tag
[root@docker ~]# curl http://192.168.200.10:5000/v2/centos/tags/list
{"name":"centos","tags":["v1.0"]}
==(7)删除原有镜像,拉取私有仓库的镜像
[root@docker ~]# docker pull 192.168.200.10:5000/centos:v1.0
v1.0: Pulling from centos
2d473b07cdd5: Pull complete
Digest: sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f
Status: Downloaded newer image for 192.168.200.10:5000/centos:v1.0
192.168.200.10:5000/centos:v1.0
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.200.10:5000/centos v1.0 eeb6ee3f44bd 23 months ago 204MB
是什么
Harbor是一个企业级镜像仓库项目,由VMware开源,每个组件以Docker容器的形式构建,通过Docker-compose进行快速部署
为什么
虽然有很多Docker公共镜像仓库,但是从安全和效率等方面考虑,部署私有镜像仓库是非常必要的:
(1)安装Docker
上面小节内容有写怎么安装,自己翻上去看
(2)下载Docker-Compose
最新版本docker-compose下载:docker-compose
其他版本docker-compose下载:docker-compose
wget https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64
重命名
[root@harbor ~]# mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
赋权
[root@harbor ~]# chmod +x /usr/local/bin/docker-compose
查版本
[root@harbor ~]# docker-compose version
Docker Compose version v2.20.3
(3)下载openssl
下载地址:https://www.openssl.org/source/old/,下载v1.1.1版本
[root@harbor ~]# ls
openssl-1.1.1l.tar.gz
解压
[root@harbor ~]# tar -zxvf openssl-1.1.1l
编译
[root@harbor ~]# yum install -y gcc gcc-c++ perl perl-devel
[root@harbor ~]# cd openssl-1.1.1l
[root@harbor openssl-1.1.1l]# ./config
[root@harbor openssl-1.1.1l]# make && make install
创建软链接
[root@harbor ~]# ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
[root@harbor ~]# ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1
查看版本
[root@harbor ~]# openssl version
OpenSSL 1.1.1l 24 Aug 2021
(4)SSL证书
创建目录
# 该目录用于存储证书文件
[root@harbor ~]# mkdir -p /usr/local/harbor/cert
[root@harbor ~]# cd /usr/local/harbor/cert/
CA证书是指由权威的数字证书颁发机构(CA,Certificate Authority)签发的数字证书。CA证书用于证明一个实体(如网站、服务器、应用程序等)的身份和可信性。
①证书私钥
[root@harbor cert]# openssl genrsa -out ca.key 4096
②生成证书
[root@harbor cert]# openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=192.168.200.20" -key ca.key -out ca.crt
openssl req
: OpenSSL命令行工具,用于生成和处理证书和密钥。-x509
: 生成自签名的证书。-new
: 生成一个新的证书请求。-nodes
: 生成无密码的私钥文件。-sha512
: 使用SHA-512算法进行签名。-days 3650
: 证书的有效期为3650天(10年)。-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=192.168.200.20"
: 设置证书的Subject字段,包括了一些组织和个人信息。
/C=CN
: 证书所属的国家或地区(中国)。/ST=Beijing
: 证书所属的省份或州(北京)。/L=Beijing
: 证书所属的城市或地区(北京)。/O=example
: 证书所属的组织名称(示例组织)。/OU=Personal
: 证书所属的组织单位(个人)。/CN=192.168.200.20
: 证书的通用名称(IP地址为192.168.200.20)。-key ca.key
: 指定私钥文件的路径和名称。-out ca.crt
: 指定生成的证书文件的路径和名称。服务器证书
服务器证书通常包含一个.crt文件可一个.key文件
①证书私钥
[root@harbor cert]# openssl genrsa -out 192.168.200.20.key 4096
②csr文件
[root@harbor cert]# openssl req -sha512 -new -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=192.168.200.20" -key 192.168.200.20.key -out 192.168.200.20.out
③v3.ext文件
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=192.168.200.20
④crt文件
通过CA证书私钥、CA证书、v3.ext扩展文件和服务器签名签发服务器证书
[root@harbor cert]# openssl x509 -req -sha512 -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in 192.168.200.20.csr -extfile v3.ext -out 192.168.200.20.crt
(1)下载
下载地址:harbor,根据自己的需求下载软件包,Harbor分为offline和online两个包,offline包含Harbor所需的镜像文件,比较全面。
[root@harbor ~]# ls
harbor-offline-installer-v2.8.3.tgz
(2)解压
[root@harbor ~]# tar -zxvf harbor-offline-installer-v2.8.3.tgz
(3)修改配置文件
[root@harbor ~]# cd harbor
[root@harbor harbor]# ls
common common.sh docker-compose.yml harbor.v2.8.3.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
[root@harbor harbor]# mv harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
# 修改如下内容
hostname: 192.168.200.20
certificate: /usr/local/harbor/cert/192.168.200.20.crt
private_key: /usr/local/harbor/cert/192.168.200.20.key
harbor_admin_password: 123456
(4)安装
[root@harbor harbor]# ./install.sh
(5)关闭防火墙
[root@harbor harbor]# systemctl stop firewalld && systemctl disable firewalld
状态:docker-compose ps
停止:docker-compose down
启动: docker -compose up -d
启动浏览器→访问https://192.168.200.20
账户:admin
密码:刚刚配置文件设置的密码
(1)修改daemon.json文件
[root@harbor harbor]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://9dkjece7.mirror.aliyuncs.com"]
"insecure-registries": ["192.168.200.20"]
}
[root@harbor harbor]# systemctl daemon-reload && systemctl restart docker
(2)上传镜像
# 先登录
[root@harbor harbor]# docker login https://192.168.200.20
# 修改标签
[root@harbor harbor]# docker tag centos:7.9.2009 192.168.200.20/library/centos:7.9.2009
# 上传
[root@harbor harbor]# docker push 192.168.200.20/library/centos:7.9.2009
# 先删除之前的centos7.9.2009镜像
[root@harbor harbor]# docker rmi -f eeb6ee3f44bd
# 拉取
[root@harbor harbor]# docker pull 192.168.200.20/library/centos:7.9.2009
# 查看
[root@harbor harbor]# docker images 192.168.200.20/library/centos
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.200.20/library/centos 7.9.2009 eeb6ee3f44bd 23 months ago 204MB
容器中的管理数据主要有两种方式:
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似Linux的mount
数据卷有哪些特性?
使用docker volume
来管理数据卷,如下命令可以创建一个数据卷
# 创建数据卷
[root@docker ~]# docker volume create -d local test
# 查看你数据卷位置
[root@docker ~]# ls -l /var/lib/docker/volumes/
drwx-----x. 3 root root 19 8月 13 21:55 test
除了create命令之外,docker volume
还支持inspect
(查看详细信息)、ls
(列出已有数据卷)、prune
(清理无用数据卷)、rm
(删除数据卷)等
出了可以用docker volume 来管理数据卷之外,还可以在创建容器时将主机本地的任意路径挂载到容器内作为数据卷
使用docker run
命令的时候,可以使用 -mount选项来使用数据卷
--mount
选项支持三种类型的数据卷
volume
:普通数据卷,映射到主机/var/lib/docker/volumes路径下bind
: 绑定数据卷,映射到主机指定的路径下tmpfs
:临时数据卷,只存在于内存中--mount常用子参数:
type
:指定挂载类型source
:指定挂载源,对于 type=bind
,表示主机上的路径,对于 type=volume
,表示数据卷名称。destination
:指定挂载到容器中的目标路径下面使用httpd镜像创建一个Web容器,并将刚刚创建的数据卷挂载到容器内的/usr/local/apache2/htdocs/目录
[root@docker ~]# docker run -d -P --name web --mount type=volume,source=test,destination=/usr/local/apache2/htdocs/ httpd
# 查看test数据卷的位置
[root@docker ~]# docker volume inspect test
[
{
"CreatedAt": "2023-08-13T21:55:33+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/test/_data",
"Name": "test",
"Options": null,
"Scope": "local"
}
]
# 进入数据卷看看index.html站点目录是否被挂载出来了
[root@docker ~]# cd /var/lib/docker/volumes/test/_data/
[root@docker _data]# ls
index.html
# 修改站点目录文件
[root@docker _data]# echo "I am ChenShiRen
" > index.html
# 查看随机开放的端口
[root@docker _data]# netstat -ltnp |grep docker
tcp 0 0 0.0.0.0:32768 0.0.0.0:* LISTEN 118078/docker-proxy
tcp6 0 0 :::32768 :::* LISTEN 118085/docker-proxy
浏览器访问
接下来使用一下bind数据卷类型绑定数据卷,bind其实跟 -v 这个参数使用效果是一样的,但是这样挂载的数据卷不好管理,docker volume ls 是查不到的
# 先创建挂载目录
[root@docker ~]# mkdir /web
# 写入站点文件
[root@docker ~]# echo "I am CSR
" > /web/index.html
# 运行容器,使用mount
[root@docker ~]# docker run -d -p 8899:80 --name web2 --mount type=bind,source=/web,destination=/usr/local/apache2/htdocs/ httpd
# 运行容器,使用-v
[root@docker ~]# docker run -d -p 8899:80 --name web2 -v /web:/usr/local/apache2/htdocs/ httpd
# 查看数据卷
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local test
浏览器访问
需要注意的是本地目录的路径必须是绝对路径,容器内的路径可以是相对路径,如果目录不存在,docker会自动创建
docker挂载数据卷默认权限是读写(rw),用户也可以通过(ro)指定只读:
注意,加入ro之后容器内对所挂载的数据卷的数据就无法被修改了
[root@docker ~]# docker run -d -p 2234:80 --name web4 -v /webapp:/usr/local/apache2/htdocs/:ro httpd
# 可以看到我没有创建/webapp这个目录,docker自动给我创建的
[root@docker ~]# ls /webapp/
# 写入站点文件
[root@docker ~]# echo "i am csr" > /webapp/index.html
# 进入容器看看是否能被修改
[root@docker ~]# docker exec -it web4 /bin/bash
root@cf0b7ee929d8:/usr/local/apache2# cd htdocs/
root@cf0b7ee929d8:/usr/local/apache2/htdocs# ls
index.html
root@cf0b7ee929d8:/usr/local/apache2/htdocs# rm -rf index.html
rm: cannot remove 'index.html': Read-only file system
# 修改不了
root@cf0b7ee929d8:/usr/local/apache2/htdocs# ls -l
-rw-r--r--. 1 root root 16 Aug 13 15:33 index.html
浏览器访问也是没有问题的
如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器
首先将本地数据卷/data挂载到容器中的/data中,使用centos:7.9.2009镜像
[root@docker ~]# docker run -d -it -v /data:/data --name centos centos:7.9.2009 /bin/bash
[root@docker ~]# docker exec -it centos /bin/bash
[root@7d03083da61c /]# ls / |grep data
data
[root@docker ~]# ls / |grep data
data
然后,创建其他容器中使用 --volumes-from 来挂载容器中的data数据卷,先创建centos2和centos3两个容器,并从data容器挂载数据卷
[root@docker ~]# docker run -it -d --volumes-from centos --name centos2 centos:7.9.2009
[root@docker ~]# docker run -it -d --volumes-from centos --name centos3 centos:7.9.2009
在本地/data写入一些文件看看,这三个容器内是否会同步
[root@docker ~]# echo "hello world!" > /data/hello.txt
[root@docker ~]# docker exec -it centos2 /bin/cat /data/hello.txt
hello world!
[root@docker ~]# docker exec -it centos3 /bin/cat /data/hello.txt
hello world!
[root@docker ~]# docker exec -it centos /bin/cat /data/hello.txt
hello world!
使用 --volumes-from 参数所挂载数据卷的容器自身并不需要保持在运行状态
可以利用数据卷容器对其中的数据进行备份、恢复,以实现数据卷迁移
使用如下命令备份centos中的数据到容器中的/data目录下,然后同步到本机/data
[root@docker ~]# docker run -it -d --volumes-from centos -v ${PWD}:/backup --name centos-backup centos:7.9.2009
[root@docker ~]# docker exec -it centos-backup tar -cf /data/centos-backup.tar.gz backup
# 同步到了本地,容器内还有一份
[root@docker ~]# du -h /data/centos-backup.tar.gz
669M /data/centos-backup.tar.gz
# 查看容器内,另一个容器内
[root@docker ~]# docker exec -it centos du -h /data/centos-backup.tar.gz
669M /data/centos-backup.tar.gz
如何恢复呢,使用如下命令,将数据恢复到另一个容器内的/opt/目录下
[root@docker ~]# docker run -it -d --volumes-from centos --name hf centos:7.9.2009 /bin/bash
[root@docker ~]# docker exec -it hf tar -x /data/centos-backup.tar.gz -C /opt/
[root@docker data]# docker exec -it hf du -h /opt/backup
669M /opt/backup
在实践中经常会碰到需要多个服务组件共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。
Docker出了通过网络访问外,还提供了两个很方便的功能来满足服务访问的基本需求:一个是运行映射容器内应用的服务端口到本地宿主机;另一个是互联机制实现多个容器间通过容器名来快速访问。
在启动容器时需要指定对应的参数,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的
当容器中运行一些网络应用时,要让外部访问这些应用时,可以通过 -P 或 -p 参数来指定端口映射。当使用 -P(大写) 时,Docker会随机映射一个端口到内部容器
[root@docker ~]# docker run -d -P --name web httpd
2a5c57440a724637196a10f4c82ee971a5bcc9f8b3989c118613333f3a7345e3
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a5c57440a72 httpd "httpd-foreground" 2 seconds ago Up 2 seconds 0.0.0.0:32768->80/tcp, :::32768->80/tcp web
# 可以看到本地主机的32768端口被映射到了容器中的80端口上
# 访问宿主机32768端口即可访问容器内的web界面
-p(小写) 则可以指定映射的端口,并且,在一个指定端口上只可以绑定一个容器。
支持的格式有 IP:HostPort:ContainerPort | IP::ContainerPort | HostPort:ContainerPort
可以使用 HostPort:ContainerPort
格式将本地的5000端口映射到容器的80端口
[root@docker ~]# docker run -d -p 5000:80 httpd
# 此时默认会绑定本地所有接口上的所有地址
也可以多次使用-p标记绑定多个端口
这里使用我自己做的nginx:v1.0,我使用了nginx多端口的虚拟机,这时候我们需要暴露多个端口
# 启动容器
[root@docker ~]# docker run -it -d -p 9000:9000 -p 8000:8000 -p 80:80 -v /nginxhtml:/usr/share/nginx/html/ --name mp_nginx nginx:v1.0
# 查看容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aff685712336 nginx:v1.0 "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp mp_nginx
# 开启nginx
[root@docker ~]# docker exec -it mp_nginx nginx
# 写入站点文件
[root@docker ~]# echo "Many Port NGINX
" > /nginxhtml/index.html
80端口
9000端口
8000端口
可以使用IP:HostPort:ContainerPort
格式指定映射使用一个特定地址,比如192.168.200.10(本机地址)
[root@docker ~]# docker run -it -d -p 192.168.200.10:9000:9000 -v /nginxhtml:/usr/share/nginx/html --name ip_nginx1 nginx:v1.0
使用IP::ContainerPort
绑定192.168.200.10的随机端口到容器的9000端口。
[root@docker ~]# docker run -it -d -p 192.168.200.10::9000 -v /nginxhtml:/usr/share/nginx/html --name ip_nginx2 nginx:v1.0
d14f36b0d497c62d89c4c6f75af1b7348f6c9af546bb940db30105481ff4a1a8
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d14f36b0d497 nginx:v1.0 "/docker-entrypoint.…" 2 seconds ago Up 1 second 80/tcp, 192.168.200.10:32768->9000/tcp ip_nginx2
还以可以使用udp来指定udp端口
[root@docker ~]# docker run -it -d -p 192.168.200.10:9000:9000/udp -v /nginxhtml:/usr/share/nginx/html --name ip_nginx3 nginx:v1.0
使用docker port
来查看当前映射的端口配置
[root@docker ~]# docker port ip_nginx2 9000
192.168.200.10:32769
容器有自己的网络和IP,使用docker inspect 容器ID 可以获取容器的具体信息
容器的互联是一种让多个容器中的应用镜像快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体IP地址。
连接系统依据容器的名称来执行。首先需自定义一个好记的容器名。
使用–name 可以为容器自定义命名
[root@docker ~]# docker run -it -d --name centos1 centos:latest
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c04ebf49ddf1 centos:latest "/bin/bash" 4 seconds ago Up 3 seconds centos1
使用 --link参数可以让容器之间安全地进行交互
先将之前创建的自定义容器删除
[root@docker ~]# docker rm -f centos
下面创建一个新的数据库容器
[root@docker ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=000000 mysql:latest
然后创建一个新的web容器,并将它连接到db容器
[root@docker ~]# docker run -d -P --name web --link mysql:mysql httpd
# --link name:alias 其中name是链接的容器的名称,alias是别名
Docker相当于在两个容器之间创建了一个虚拟通道,而且不用映射它们的端口到宿主机上。在启动mysql容器的时候并没有使用-p 和 -P标记,从而避免了暴露数据库服务端口到外部网络上
Docker通过两种方式为容器公开连接信息
使用env命令查看web容器的环境变量
[root@docker ~]# docker run --rm --name web2 --link mysql:mysql httpd env
PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=befcbc202323
MYSQL_PORT=tcp://172.17.0.3:3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.3:3306
MYSQL_PORT_3306_TCP_ADDR=172.17.0.3
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_PORT_33060_TCP=tcp://172.17.0.3:33060
MYSQL_PORT_33060_TCP_ADDR=172.17.0.3
MYSQL_PORT_33060_TCP_PORT=33060
MYSQL_PORT_33060_TCP_PROTO=tcp
MYSQL_NAME=/web2/mysql
MYSQL_ENV_MYSQL_ROOT_PASSWORD=000000
MYSQL_ENV_GOSU_VERSION=1.12
MYSQL_ENV_MYSQL_MAJOR=8.0
MYSQL_ENV_MYSQL_VERSION=8.0.27-1debian10
HTTPD_PREFIX=/usr/local/apache2
HTTPD_VERSION=2.4.52
HTTPD_SHA256=0127f7dc497e9983e9c51474bed75e45607f2f870a7675a86dc90af6d572f5c9
HTTPD_PATCHES=
HOME=/root
其中MYSQL_开头的环境变量是供web容器连接mysql容器使用,前缀采用大写的连接别名
除了环境变量,Docker还添加host信息到父容器的/etc/hosts的文件。下面是父容器web的hosts文件
[root@docker ~]# docker exec -it web /bin/bash
root@1ed35ea4a8c9:/usr/local/apache2# cat /etc/hosts
172.17.0.3 mysql 74c518a5f3a4 # 这里写了mysql容器IP、name和ID
172.17.0.2 1ed35ea4a8c9 # 这里写了自己容器的IP、ID
可以在web容器中安装ping命令来测试mysql容器的连通
root@1ed35ea4a8c9:/usr/local/apache2# apt-get install -yqq inetutils-ping
root@1ed35ea4a8c9:/usr/local/apache2# ping mysql
PING mysql (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.214 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.094 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.095 ms
root@1ed35ea4a8c9:/usr/local/apache2# ping 74c518a5f3a4 # ping mysql容器ID也是可以的
PING mysql (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.139 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.105 ms
Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。
Dockerfile中的指令一般格式为 【指令 参数】的形式
配置指令
指令 | 说明 |
---|---|
ARG | 定义创建镜像过程中使用的变量 |
FROM |
指定所创建镜像的基础镜像 |
LABEL | 为生成的镜像添加元数据标签信息 |
EXPOSE |
声明镜像内服务监听的端口 |
ENV |
指定环境变量 |
ENTRYPOINT |
指定镜像的默认入口命令 |
VOLUME |
创建一个数据卷挂载点 |
USER | 指定运行容器时的用户名或UID |
WORKDIR | 配置工作目录 |
ONBUILD | 创建子镜像时指定自动执行的操作指令 |
STOPSIGNAL | 指定退出的信号值 |
HEALTHCHECK | 配置所启动容器如何进行健康检查 |
SHELL | 指定默认shell类型 |
操作指令
指令 | 说明 |
---|---|
RUN |
运行指定命令 |
CMD |
启动容器时指定默认执行的命令 |
ADD |
添加内容到镜像 |
COPY |
复制内容到镜像 |
定义创建镜像过程中使用的变量
格式为ARG
例如,使用ARG创建一个临时变量
[root@docker ~]# vim dockerfile
FROM centos:7.9.2009
ARG PKG=httpd
RUN yum install -y $PKG
[root@docker ~]# docker build -t centos:v1.0 -f dockerfile .
[root@docker ~]# docker run -it --name centos centos:v1.0 /bin/bash
[root@ea59827ee9a5 /]# echo ${PKG}
# ARG指定的变量将不再镜像中保留,ENV指定的变量将在镜像中保留
指定所创建镜像的基础镜像
常用格式为 FROM
任何Dockerfile中第一条指令必须为FROM指令。如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)
为了保证镜像的精简,可以选用体积较小的镜像如Alpine或Debian作为基础镜像
[root@docker ~]# vim dockerfile
ARG VERSION=9.3
FROM debian:${VERSION}
[root@docker ~]# docker build -t debian:9.3 -f dockerfile .
[root@docker ~]# docker images debian
REPOSITORY TAG IMAGE ID CREATED SIZE
debian 9.3 d636f7fb13e4 5 years ago 100MB
LABEL指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像
格式为LABEL
例如:
[root@docker ~]# vim dockerfile
ARG VERSION=9.3
FROM debian:${VERSION}
LABEL version="v1.0"
LABEL mantainer="CSQ"
LABEL description="This is a New Docker image"
[root@docker ~]# docker build -t debian:v1.0 -f dockerfile .
[root@docker ~]# docker inspect centos:v1.0
# ...(省略)....
"Labels": {
"description": "This is a New Docker image",
"mantainer": "CSQ",
"version": "v1.0"
}
# ...(省略)....
指定镜像内服务监听的端口
格式为 EXPOSE
该指令只是声明作用,并不会自动完成端口映射
如果需要映射,需要在启动容器的时候使用 -P 参数或 -p 参数
指定环境变量,在镜像生成过程中会被使用,在镜像启动后的容器中也会存在
格式为 ENV
例如:
[root@docker ~]# vim dockerfile
ARG VERSION=9.3
FROM debian:${VERSION}
LABEL version="v1.0"
LABEL mantainer="CSQ"
LABEL description="This is a New Docker image"
ENV NAME=centos-csq
[root@docker ~]# docker build -t debian:v1.0 -f dockerfile .
[root@docker ~]# docker run -it debian:v1.0 env |grep -i name
HOSTNAME=7dddb7f73a25
NAME=centos-csq
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数
支持两种格式:
ENTRYPOINT ["echo", "Hello, World!"]
:exec 调用执行ENTRYPOINT command param1 param2 ...
:shell中执行如果在Dockerfile中使用了多个ENTRYPOINT指令,只有最后一个指令会生效
创建一个数据卷挂载点,VOLUME指令允许开发者定义一个或多个目录,用于在容器中存储持久化数据或与宿主机共享文件
格式为 VOLUME ["/data",/path/aaa]
可以指定多个路径,每个路径都会在容器中被创建为一个挂载点。
指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份
格式为:USER daemon
当服务器不需要管理员权限时,可以通过该命令指定运行用户,并且可以在Dockerfile中创建所需要的用户
例如:
[root@docker ~]# vim dockerfile
ARG VERSION=9.3
FROM debian:${VERSION}
LABEL version="v1.0"
LABEL mantainer="CSQ"
LABEL description="This is a New Docker image"
ENV NAME centos-csq
RUN groupadd -r csqgroup && useradd -r -g csqgroup csquser
USER csquser
[root@docker ~]# docker build -t debian:v1.0 -f dockerfile .
[root@docker ~]# docker run -it debian:v1.0 id
uid=999(csquser) gid=999(csqgroup) groups=999(csqgroup)
指定工作目录
格式为 WORKDIR /path/to/workdir
为了避免出错,使用WORKDIR推荐使用绝对路径
[root@docker ~]# vim dockerfile
ARG VERSION=9.3
FROM debian:${VERSION}
LABEL version="v1.0"
LABEL mantainer="CSQ"
LABEL description="This is a New Docker image"
ENV NAME centos-csq
RUN groupadd -r csqgroup && useradd -r -g csqgroup csquser
USER csquser
WORKDIR /opt/
[root@docker ~]# docker build -t debian:v1.0 -f dockerfile .
[root@docker ~]# docker run -it debian:v1.0 pwd
/opt
指定当基于所生成镜像创建子镜像时,自动执行的操作命令
格式为 ONBUILD [INSTRUCTION]
例如
# 写入ONBUILD
[root@docker ~]# vim dockerfile
FROM centos:7.9.2009
COPY csq.txt /opt/
RUN yum install -y net-tools
ONBUILD RUN yum install -y httpd
ONBUILD RUN echo "onbuild---httpd" > /usr/share/httpd/noindex/index.html
ONBUILD EXPOSE 80
ONBUILD CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
[root@docker ~]# echo "I am csq" >> csq.txt
[root@docker ~]# docker build -t centos:v1.0 -f dockerfile .
[root@docker ~]# docker run -it centos:v1.0 ls /opt/
csq.txt
[root@docker ~]# docker run -it centos:v1.0 yum list installed |grep net-tools
net-tools.x86_64 2.0-0.25.20131004git.el7 @base
[root@docker ~]# docker run -it centos:v1.0 yum list installed |grep httpd
# 找不到httpd安装包,没有安装httpd
# 基于centos:v1.0再次创建镜像
[root@docker ~]# vim dockerfile-2
FROM centos:v1.0
[root@docker ~]# docker build -t centos:v2.0 -f dockerfile-2 .
[root@docker ~]# docker run -it -d --name centos-http -p 80:80 centos:v2.0 /bin/bash
指定创建镜像启动的容器接收退出的信号值:
STOPSIGNAL signal
配置所启动容器如何进行健康检查(如何判断健康与否)
格式有两种:
OPTION支持如下参数:
SHELL指令在Dockerfile中用于设置容器的默认shell。它允许我们指定在容器中执行命令时使用的默认shell。
默认值为 SHELL["/bin/sh", "-c"]
RUN指令运行指定命令
常用格式为 RUN
每条RUN指令将再当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长可以使用 \ 来换行
例如:
RUN sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config && \
setenforce 0 && \
systemctl stop firewalld && \
systemctl disable firewalld
CMD指令用来指定启动容器时默认执行的命令
格式:
CMD ["echo", "Hello, World!"]
:相当于执行 echo Hello World!CMD echo "Hello, World!
:在默认的Shell执行,提供给需要交互的应用添加内容到镜像
格式为 ADD
该目录将复制本机路径下的内到容器中的路径下
其中可以是Dockerfile所在目录的相对路径;也是一个URL;还可以是tar文件(自动解压为目录) 可以是绝对路径,或者是相对于工作目录(WORKDIR)的相对路径
复制内容到镜像
格式为 COPY
复制本机文件或目录到镜像中的中。目标路径不存在时,会自动创建
ENTRYPOINT:指定这个启动的时候启动的时候要运行的命令,可以被替代
CMD:指定这个启动的时候启动的时候要运行的命令,可以追加命令
测试CMD
# 准备测试文件
[root@docker ~]# vim dockerfile
FROM centos:7.9.2009
CMD ["ls","-a"]
[root@docker ~]# docker build -t centos:v1.0 -f dockerfile .
[root@docker ~]# docker run centos:v1.0
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
# ...(省略)...
# 在后面追加参数
[root@docker ~]# docker run centos:v1.0 -l
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
# 报错,这是因为使用cmd的情况下,-l 替换了cmd的命令操作
[root@docker ~]# docker run centos:v1.0 ls -al
total 12
drwxr-xr-x. 1 root root 6 Aug 15 07:33 .
drwxr-xr-x. 1 root root 6 Aug 15 07:33 ..
-rwxr-xr-x. 1 root root 0 Aug 15 07:33 .dockerenv
-rw-r--r--. 1 root root 12114 Nov 13 2020 anaconda-post.log
lrwxrwxrwx. 1 root root 7 Nov 13 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Aug 15 07:33 dev
drwxr-xr-x. 1 root root 66 Aug 15 07:33 etc
drwxr-xr-x. 2 root root 6 Apr 11 2018 home
....
# 成功
测试ENTRYPOINT
# 修改测试文件
[root@docker ~]# vim dockerfile
FROM centos:7.9.2009
ENTRYPOINT ["ls","-a"]
[root@docker ~]# docker build -t centos:v2.0 -f dockerfile .
[root@docker ~]# docker run centos:v2.0
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
lib64
media
....
.....
# 加参数
[root@docker ~]# docker run centos:v2.0 -l
total 12
drwxr-xr-x. 1 root root 6 Aug 15 07:36 .
drwxr-xr-x. 1 root root 6 Aug 15 07:36 ..
-rwxr-xr-x. 1 root root 0 Aug 15 07:36 .dockerenv
-rw-r--r--. 1 root root 12114 Nov 13 2020 anaconda-post.log
lrwxrwxrwx. 1 root root 7 Nov 13 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Aug 15 07:36 dev
drwxr-xr-x. 1 root root 66 Aug 15 07:36 etc
drwxr-xr-x. 2 root root 6 Apr 11 2018 home
lrwxrwxrwx. 1 root root 7 Nov 13 2020 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 13 2020 lib64 -> usr/lib64
drwxr-xr-x. 2 root root 6 Apr 11 2018 media
drwxr-xr-x. 2 root root 6 Apr 11 2018 mnt
# 成功
# 加入完整参数
[root@docker ~]# docker run centos:v2.0 ls -al
ls: cannot access ls: No such file or directory
# 报错,这是因为使用ENTRYPOINT情况下
# ls -al 替换了ENTRYPOINT参数,但是找不到这个参数所以报错了
# 准备测试文件
[root@docker ~]# ls
csq.txt dockerfile xxx.tar.gz
[root@docker ~]# vim dockerfile
FROM centos:7.9.2009
COPY xxx.tar.gz /tmp/
ADD xxx.tar.gz /opt/
# 测试
[root@docker ~]# docker build -t centos:v1.0 -f dockerfile .
[root@docker ~]# docker run -it centos:v1.0 ls /opt/
a b c d e f g
[root@docker ~]# docker run -it centos:v1.0 ls /tmp/
ks-script-DrRL8A xxx.tar.gz yum.log
# ADD 自动解压 tar 文件然后传输到容器中
# COPY 会原封不动的将文件传输到容器中
编写完成Dockerfile之后,可以通过docker [image] build
命令来创建镜像
该命令将读取指定路径下的Dockerfile,并将该路径下所有数据作为上下文发送给Docker服务端。Docker服务端在校验Dockerfile格式通过后,逐条执行其中定义的指令,碰到ADD、COPY、RUN指令会生成一层新的镜像。最终如果创建镜像成功,就会返回最终的镜像ID
如果使用非上下文路径下的Dockerfile,可以使用 -f 选项来指定路径
如果要生成指定镜像标签信息,可以通过 -t 选项
例如,上下文路径为/opt/dockerfile_1 并且希望生成的标签为 csq/centos:v1.0,可以使用如下命令
docker build -t csq/centos:v1.0 -f /opt/dockerfile_1 .
构建镜像的常用命令选项
选项 | 说明 |
---|---|
-f | Dockerfile名称 |
-m | 限制使用内存量 |
–network | 指定网络模式 |
-q | 不打印创建过程中的日志信息 |
-t | 指定镜像标签 |
生成新的镜像都需要通过FROM指令来指定父镜像。父镜像是生成镜像的基础,会影响到所生成镜像的大小和功能
用户可以选择两种镜像作为父镜像,一种是所谓的基础镜像,另一种是普通镜像(第三方镜像)
在Docker中,可以使用.dockerignore
文件来指定在构建镜像时需要忽略的文件和目录。
支持以下几种模式:
" * "
表示任意多个字符" ? "
表示单个字符" ! "
表示不匹配(即不忽略指定路径或文件)注意事项:
.dockerignore
文件需要与Dockerfile
文件位于同一目录下.dockerignore
文件中的每一行表示一个匹配规则Docker多步骤创建是一种构建Docker镜像的技术,它通过多个构建阶段(步骤)来分解复杂的构建过程,以减小最终镜像的体积。
多步骤创建的主要优点有:
减小镜像体积
:通过分解构建过程并在每个阶段中只保留必要的文件和操作,可以减小最终构建的镜像的体积。这对于减少镜像下载和传输的时间非常有帮助。
提高安全性
:多步骤创建可以确保最终的Docker镜像中只包含必要的文件和配置,减少了潜在的安全风险。
提高构建速度
:通过将构建过程分解为多个阶段,可以重用已构建的中间镜像,从而加快构建速度。
以C语言应用为例
创建main.c文件,内容为:
#include
int main()
{
printf ("Hello,Docker!\n");
return 0;
}
创建Dockerfile,使用centos:7.9.2009镜像编译应用二进制文件为myprogram,使用镜像debian:9.3作为运行环境,Dockerfile完整内容为
[root@docker ~]# vim Dockerfile
FROM centos:7.9.2009 AS builder
RUN yum install -y gcc
WORKDIR /app
COPY main.c .
RUN gcc -o myprogram main.c
FROM debian:9.3
WORKDIR /root
COPY --from=builder /app/myprogram .
CMD ["./myprogram"]
创建镜像并运行应用
[root@docker ~]# docker build -t myc-1 -f Dockerfile .
[root@docker ~]# docker run myc-1
Hello,Docker!
Apache是一个开源的、跨平台的Web服务器软件,全称为Apache HTTP Server。它是目前互联网上最流行的Web服务器之一,广泛应用于各种网站和Web应用的搭建和部署中。 Apache最初由美国国家超级计算应用中心(NCSA)开发,后来由于其开源的特性,吸引了全球范围内的开发者参与到项目中,逐渐发展成为一个独立的、由Apache软件基金会管理的项目。Apache软件基金会是一个非营利性的组织,致力于支持和发展开源软件项目。
(1)编写Dockerfile文件
FROM httpd:2.4
COPY ./public-html /usr/local/apache2/htdocs/
(2)编写项目目录public-html,并在此目录下创建index.html文件
[root@docker ~]# mkdir public-html
[root@docker ~]# vim public-html/index.html
<h1><b>Hello Docker</b></h1>
(3)构建自定义镜像
[root@docker ~]# docker build -t apache2-image:v1.0 -f Dockerfile-apache .
(4)运行容器
[root@docker ~]# docker run -itd -p 8000:80 apache2-image:v1.0
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db3f9f3434fa apache2-image:v1.0 "httpd-foreground" 3 seconds ago Up 2 seconds 0.0.0.0:8000->80/tcp, :::8000->80/tcp objective_heisenberg
浏览器访问
也可以不创建自定义镜像,直接通过映射目录方式运行Apache容器
docker run -itd --rm --name my-apache-app -p 8000:80 -v /apachehtml:/usr/local/apache2/htdocs/ httpd:2.4
(1)首先创建一个apache_centos 工作目录,在其中创建Dockerfile文件和站点文件index.html
[root@docker ~]# mkdir apache_centos && cd apache_centos/
[root@docker apache_centos]# touch Dockerfile
[root@docker apache_centos]# touch index.html
(2)编写Dockerfile
[root@docker apache_centos]# cat Dockerfile
FROM centos:7.9.2009
MAINTAINER CSQ
RUN yum install -y epel-release && yum install -y httpd && rm -rf /var/www/html/*
COPY index.html /var/www/html/index.html
EXPOSE 80
CMD ["httpd","-D","FOREGROUND"]
(3)编写站点文件
[root@docker apache_centos]# echo "Centos:7.9.2009 Apache
" >> index.html
(4)构建自定义镜像
[root@docker apache_centos]# docker build -t centos-apache:v1.0 .
(5)运行容器
[root@docker apache_centos]# docker run -itd -p 80:80 centos-apache:v1.0
[root@docker apache_centos]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
560f64397d05 centos-apache:v1.0 "httpd -D FOREGROUND" 2 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp strange_shaw
(6)浏览器访问
Nginx(发音为"engine-x")是一个高性能的开源Web服务器和反向代理服务器。它的设计目标是提供高性能、高并发的服务,并具备良好的可扩展性和稳定性。Nginx以其卓越的性能和灵活的配置而受到广泛的关注和使用。
直接使用docker run指令运行官方Nginx镜像
[root@docker ~]# docker run -d -p 80:80 --name webnginx nginx
使用docker ps查看当前运行的容器
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d646a73ebb0 nginx "/docker-entrypoint.…" 3 hours ago Up 3 hours 0.0.0.0:80->80/tcp, :::80->80/tcp webnginx
自定义web页面
首先新建index.html文件
<html>
<title>text</title>
<body>
<div >
hello world
</div >
<body>
</html>
然后使用docker run指令,并将/nginxhtml挂载至容器中,将index.html放入挂载的文件内,即可看到自定义页面
[root@docker ~]# docker run -d --name nginx-container -p 80:80 -v index.html:/usr/share/nginx/html/index.html:ro nginx
[root@docker ~]# mv index.html /nginxhtml/index.html
也可以用Dockerfile来构建
FROM nginx
COPY ./index.html /usr/share/nginx/html/index.html
构建nginx:v1.0镜像
[root@docker ~]# docker build -t nginx:v1.0 -f Dockerfile-nginx .
构建成功运行容器
[root@docker ~]# docker run -d --name nginx-container -p 80:80 nginx:v1.0
c1e50d3fa49acf79cf7a5b495e650a99f5e8d34ae2d6f540261699053309b101
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c1e50d3fa49a nginx:v1.0 "/docker-entrypoint.…" 2 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp nginx-container
浏览器访问
[root@docker ~]# vim Dockerfile-nginx
FROM centos:7.9.2009
MAINTAINER CSQ
RUN yum install -y epel-release && yum install -y nginx
RUN rm -rf /usr/share/nginx/html/*
COPY index.html /usr/share/nginx/html/index.html
RUN /bin/bash -c 'echo init ok'
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
构建镜像
[root@docker ~]# docker build -t nginx:v2.0 -f Dockerfile-nginx .
运行容器
[root@docker nginx-web]# docker run -d -P nginx:v2.0
[root@docker nginx-web]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d0f81fa086eb nginx:v2.0 "nginx -g 'daemon of…" 2 seconds ago Up 1 second 0.0.0.0:32818->80/tcp, :::32798->80/tcp bold_haibt
访问本地32798端口
[root@docker nginx-web]# curl localhost:32798
<html>
<title>text</title>
<body>
<div >
hello world
</div >
<body>
</html>
Tomcat是一个开源的Java Servlet容器,也是一个用于开发和部署Java Web应用的服务器软件。它由Apache软件基金会开发和维护,是目前最流行的Java Web服务器之一
下载tomcat地址:tomcat下载地址
下载jdk地址:JDK下载地址
# 下载tomcat和jdk
[root@docker ~]# ls
apache-tomcat-8.5.92.tar.gz jdk-8u144-linux-x64.tar.gz
# 解压
[root@docker ~]# ls
apache-tomcat-8.5.92 jdk1.8.0_144
# 重命名方便复制
[root@docker ~]# mv apache-tomcat-8.5.92 tomcat
[root@docker ~]# mv jdk1.8.0_144/ jdk180
FROM centos:7.9.2009
MAINTAINER CSQ
RUN mkdir -p /docker_home/local
ADD tomcat /docker_home/local/tomcat8
ADD jdk180 /docker_home/local/java180
ENV JAVA_HOME /docker_home/local/java180
ENV TOMCAT_HOME /docker_home/local/tomcat8
ENV PATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin
EXPOSE 8080
CMD ["/docker_home/local/tomcat8/bin/catalina.sh","run"]
构建镜像
[root@docker ~]# docker build -t tomcat:v1.0 -f Dockerfile-tomcat .
运行容器
[root@docker ~]# docker run -d -p 8888:8080 --name tomcat tomcat:v1.0
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a10b5df29917 tomcat:v1.0 "/docker_home/local/…" 2 seconds ago Up 1 second 0.0.0.0:8888->8080/tcp, :::8888->8080/tcp tomcat
浏览器访问
MySQL是一种开源的关系型数据库管理系统(RDBMS),它由瑞典MySQL AB公司开发,并由Oracle公司持有和维护。MySQL是目前世界上最流行的开源数据库之一,被广泛应用于各种Web应用和企业级应用中。
可以使用官方镜像快速启动一个MySQL Server实例:
[root@docker ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=000000 -d mysql:latest
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6710a96b8901 mysql:latest "docker-entrypoint.s…" 9 minutes ago Up 9 minutes 3306/tcp, 33060/tcp mysql
可以使用–link 标签将一个应用容器连接到MySQL容器
docker run -itd --rm --name my-apache-app -p 8000:80 --link mysql:mysql httpd:2.4
[root@docker ~]# docker exec -it my-apache-app cat /etc/hosts
172.17.0.3 mysql 1a715a94b48a
172.17.0.4 af1efed1537c
官方镜像还可以作为客户端,连接非Docker或者远程的MySQL案例
[root@docker ~]# docker run -it --rm mysql mysql -h192.168.200.10 -uroot -p000000
mysql>
MySQL Server 日志可以使用docker logs指令查看
[root@docker ~]# docker logs mysql
Redis(Remote Dictionary Server)是一个开源的高性能键值存储系统,也被称为数据结构服务器。Redis支持多种数据结构,包括字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等,可以满足各种不同的应用场景需求。
可以通过docker run 指令来启动要给redis-container容器
[root@docker ~]# docker run -d --name redis-container redis
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
72b71a99c90e redis "docker-entrypoint.s…" 18 seconds ago Up 17 seconds 6379/tcp redis-container
# 进入容器
[root@docker ~]# docker exec -it redis-container /bin/bash
# 开启redis服务
root@ab65037185f0:/data# redis-server
# 进入redis客户端
root@ab65037185f0:/data# redis-cli
# 测试服务是否可用
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> mset name csq
OK
127.0.0.1:6379> mget name
1) "csq"
连接redis容器,用户可以使用 --link 参数,连接创建的reids-container容器
[root@docker ~]# docker run -it --link redis-container:db alpine sh
[root@docker ~]# docker exec -it redis-container /bin/bash
进入alpine系统容器后,可以使用ping命令测试redis容器
/ # ping db
PING db (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.259 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.104 ms
也可以用一个redis连接另一台redis服务
[root@docker ~]# docker run -it --link redis-container:db --entrypoint redis-cli redis -h db
db:6379> ping
PONG
db:6379> mget name # 我们之前定义的值还在
1) "csq"
db:6379> set k1 v1 k2 v2 k3 v3
(error) ERR syntax error
db:6379> mset k1 v1 k2 v2 k3 v3
OK
db:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
[root@docker ~]# vim Dockerfile-redis
FROM centos:centos7.9.2009
MAINTAINER CSQ
RUN yum install -y epel-release && yum install -y redis
RUN sed -i 's/127.0.0.1/0.0.0.0/g' /etc/redis.conf && \
sed -i 's/protected-mode yes/protected-mode no/g' /etc/redis.conf
EXPOSE 6379
CMD ["/usr/bin/redis-server","/etc/redis.conf"]
构建镜像
[root@docker ~]# docker build -t redis:v1.0 -f Dockerfile-redis .
运行容器
[root@docker ~]# docker run -d -p 192.168.200.10:6379:6379 --name redis redis:v1.0
使用RedisInsight可视化工具连接 redis客户端
Docker-compose是Docker官方开源的项目,负责实现对基于Docker容器多应用服务的快速编排。功能上有点类似于Openstack 的 Heat模板
Docker-compose是一个用于定义和管理多容器Docker应用程序的工具,前面学习Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在工作中经常会碰到需要多个容器相互配合来完成某项任务。例如实现一个Web项目,除了web服务本身还需要数据库服务,nginx服务等,docker-compose满足了这样的需求,它允许用户通过一个单独的docker-compose.yaml模板文件来定义一组相关联的应用容器
# 安装 pip
yum -y install epel-release
yum -y install python-pip
pip install --upgrade pip
# 安装Docker-Compose
pip install docker-compose
# 查看版本
[root@localhost ~]# docker-compose -version
docker-compose version 1.26.2, build unknown
解决方法
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
python get-pip.py
pip install --upgrade setuptools
下载地址:https://github.com/docker/compose/releases
选择版本下载即可
# 下载
wget https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64
# 重命名
[root@docker ~]# mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
# 提权
[root@docker ~]# chmod +x /usr/local/bin/docker-compose
# 安装完成
[root@docker ~]# docker-compose -v
Docker Compose version v2.20.3
# 如果是二进制包的方式安装的,删除二进制文件即可
[root@docker ~]# rm -rf /usr/local/bin/docker-compose
# 如果是pip工具安装的,执行如下命令删除
[root@docker ~]# pip uninstall docker-compose
模板文件是compose的核心,默认的模板文件名称为docker-compose.yaml,目前最新的版本为v3
关于Compose版本:版本信息查看
官方文档指令查看:命令查看
Compose模板文件主要命令
命令 | 功能 |
---|---|
build | 指定Dockerfile所在文件夹的路径 |
cap_add,cap_drop | 添加或删除容器功能 |
command | 覆盖容器启动后默认执行命令 |
cgroup_parent | 指定父cgroup组,意味着将继承该组的资源限制 |
container_name | 指定容器的名称 |
devices | 指定容器设备映射关系 |
depends_on | 指定多个服务之间的依赖关系 |
dns | 自定义DNS服务器 |
dns_search | 配置DNS搜索域 |
dockerfile | 指定额外的编译镜像的Dockerfile |
entrypoint | 覆盖容器中默认的入口命令 |
env_file | 从文件中获取环境变量 |
environment | 设置环境变量 |
expose | 暴露端口,但不映射到宿主机,制备连接的服务访问 |
extends | 基于其他模板文件进行扩展 |
external_links | 链接到docker-compose.yaml外部的容器 |
extra_hosts | 指定额外的host名称映射信息 |
healthcheck | 指定检测应用健康状态的机制 |
image | 指定为镜像名称或镜像ID |
isolation | 指定容器的隔离机制 |
labels | 为容器添加Docker元数据信息 |
links | 链接到其他服务中的容器 |
logging | 跟日志相关的配置 |
network_mode | 设置网络模式 |
networks | 所加入的网络 |
pid | 跟主机系统共享进程命名空间 |
ports | 暴露端口信息 |
secrets | 配置应用的秘密数据 |
security_opt | 指定容器模板标签机制值的默认属性 |
stop_grace_period | 指定应用停止时,容器的优雅停止期限。 |
stop_signal | 指定停止容器的信号 |
sysctls | 配置容器内的内核参数 |
ulimits | 指定容器的ulimits限制值 |
userns_mode | 指定用户命名空间模式 |
volume | 数据卷所挂载路径设置 |
restart | 重启策略 |
deploy | 指定部署和运行时的容器相关配置 |
配置指令
部分指令的用法
build
命令用于构建docker-compose.yml
文件中定义的服务的镜像。
指定Dockerfile所在文件夹的路径(可以是绝对路径,也可以是相对于yaml文件的路径)
如果Dockerfile位于与docker-compose.yml
文件相同的目录中,可以使用相对路径指定上下文路径和Dockerfile的名称。例如:
version: "3"
services:
web:
build: .
如果Dockerfile位于不同的目录中,可以使用绝对路径或相对于docker-compose.yml
文件的相对路径来指定上下文路径和Dockerfile的位置
version: "3"
services:
web:
build:
context: ./path/to/context
dockerfile: Dockerfile.custom
build指令还可以指定标签、参数、Shm大小和缓存来源
args
添加构建参数,这些参数是仅在构建过程中可访问的环境变量
首先,在 Dockerfile 中指定参数:
FROM centos:7.9.2009
MAINTAINER CSQ
ARG name
WORKDIR /opt/
RUN echo "build container name: $name" > test.txt
然后build键下指定参数
version: "3"
services:
web:
build:
context: /root/
dockerfile: Dockerfile
args:
name: centos
[root@docker ~]# docker-compose up -d
[root@docker ~]# docker run -it root-web:latest cat /opt/test.txt
build container name: centos
cache_from
build:
context: .
cache_from:
- image1
- image2
image1
、image2
等是已存在的镜像名称或镜像标签。可以指定多个缓存来源,以便在构建过程中重用这些镜像的缓存层。
labels
使用Docker 标签将元数据添加到生成的镜像中
build:
context: .
labels:
maintainer: "csq"
Shm_size
设置此构建容器的分区大小
build:
context: .
shm_size: '2gb'
network
指定容器所属的网络
build:
context: .
network: host
# host 表示服务将使用主机网络模式
build:
context: .
network: none
# none 表示在构建期间禁用网络
添加或删除容器功能
# 让容器拥有所有能力可以指定为:
cap_add:
- ALL
# 去掉NET_ADMIN和SYS_ADMIN能力可以指定为:
cap_drop:
- NET_ADMIN
- SYS_ADMIN
覆盖容器启动后默认执行的命令
可以为字符串格式
command: echo "hello Docker"
或者JSON数据格式
command: ["bash", "-c", "echo", "hello Docker"]
指定父cgroup组,意味着将继承该组的资源限制
例如,创建了一个cgroup组名称为cgroups_1
cgroup_parent: cgroups_1
指定容器名称
container_name: my-web:v1.0
需要注意的是指定容器名称后,该服务将无法进行扩展,因为Docker不允许多个容器实例重名
指定设备映射关系
devices:
- "/dev/ttyUSB1:/dev/ttyUSB0"
指定多个服务之间的依赖关系。启动时,会先启动被依赖服务,例如,可以指定依赖于db服务
denpends_on: db
自定义DNS服务器。可以是一个值,也可以是一个列表
dns: 8.8.8.8
dns:
- 8.8.8.8
- 114.114.114.114
配置DNS搜索域。可以是一个值,也可以是一个列表
dns_search: example.com
dns_search:
- domain1.example.com
- domain2.example.com
如果需要,指定额外的编译镜像的Dockerfile文件,可以通过该指令来指定,例如
dockerfile: Dockerfile-abc
该指令不可以和image同时使用,否则Compose将不知道根据哪个指令来生成最终的服务镜像
覆盖容器中默认的入口命令
entrypoint: python app.py
从文件中获取环境变量,可以为单独的文件路径或列表。如果有变量名称与environment指令冲突,则以后者为准
env_file: .env
env_file:
- ./common.env
- ./root/web.env
- ./opt/abc.env
环境变量文件中每一行必须符合格式,支持#开头的注释行
# Set Rails/Rack environment
RACK_ENV=development
设置环境变量,可以使用数组或字段两种格式。只要给定名称的变量会自动获取运行Compose主机上对应变量的值,可以用来防止泄露不必要的数据
environment:
MYSQL_ROOT_PASSWORD: root
或者
environment:
- MYSQL_ROOT_PASSWORD=root
注意,如果变量名称或者值中用到 true|false ,yes|no 等表达布尔含义的词汇,最好放到引号里面,避免YAML自动解析某些内容为对应的布尔语义
https://yaml.org/type/bool.html 中给定了这些特定的词汇,包括
暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数,如下所示
expose:
- "3000"
- "9000"
基于其他模板文件进行扩展。例如,我们已经有了一个webapp服务,定义一个基础模板文件为common.yaml,如下所示
# Dockerfile-web
FROM centos:centos7.9.2009
RUN yum install -y httpd
WORKDIR /etc/httpd/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
# common.yaml
version: '3'
services:
myweb:
build: ./Dockerfile-web
environment:
- maintainer: csq
再编写一个新的development.yaml文件,使用common.yaml中的myweb服务进行扩展
version: '3'
services:
web:
extends:
file: common.yaml
service: myweb
ports:
- "8000:80"
links:
- db
depends_on:
- db
environment:
- maintainer=csq
db:
image: postgres
运行docker-compose
[root@docker ~]# docker-compose -f development.yaml up -d
浏览器访问
后者会自动继承common.yaml中的myweb服务及环境变量定义。使用extends需要注意下面两点:
一般情况下,基础模板定义一些共享镜像和环境变量,在扩展模板中具体指定应用变量、链接、数据卷等信息
链接到docker-compose.yaml 外部的容器,并非Compose管理的外部容器也可以链接
例如
services:
myservice:
image: myimage
external_links:
- external_container_name:alias
类似Docker中的 --add-host参数,指定额外的host名称映射信息
extra_hosts:
- "chenshiren:8.8.8.8"
会在启动后的服务容器中 /etc/hosts文件中添加如下内容
8.8.8.8 chenshiren
指定检测应用监控状态的机制,包括检测方法(test)、间隔(interval)、超时(timeout)、重试次数(retries)、启动等待时间(start_period)等
例如,指定检测方法为访问8080端口,间隔为30秒,超时为15秒,重试3次,启动后等待30秒再做检查
healthcheck:
test: ["CMD","curl","-f","http://localhost:8080"]
interval: 30s
timeout: 15s
retries: 3
start_period: 30s
指定镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取这个镜像
image: ubuntu
image: f0b4b9abdf1d
配置容器隔离的机制,包括 default、process和hyperv
为容器添加Docker元数据信息。例如可以为容器添加辅助说明信息
labels:
mantainer: csq
release: v1.0
links命令属于旧的用法,可能后续的版本会移除
链接到其他服务中的容器。指定服务名称和链接别名 ( "SERVICE:ALIAS"
),或者仅指定服务名称
web:
links:
- "db"
- "db:database"
- "redis"
使用的别名将会自动在服务容器中的/etc/hosts里创建
172.17.2.186 db
172.17.2.186 database
172.17.2.186 redis
被链接容器相应的环境变量也将被创建
跟日志相关的配置,包括一系列的子配置
logging.driver:指定日志驱动类型。目前支持三种日志驱动类型
driver: "json-file"
driver: "syslog"
driver: "none"
logging.options:日志驱动的相关参数。例如
services:
myservice:
image: myimage
logging:
driver: json-file
options:
max-size: 10m
max-file: 3
services:
myservice:
image: myimage
logging:
driver: syslog
设置网络模式
network_mode: "none"
network_mode: "bridge"
network_mode: "host"
所加入的网络。需要在顶级的networks字段中定义具体的网络信息
例如,创建一个自定义网络并将多个服务容器连接到该网络
version: '3'
services:
web:
image: nginx
networks:
- mynetwork
db:
image: mysql
networks:
- mynetwork
networks:
mynetwork:
driver: bridge
跟主机系统共享进程命名空间。打开该选项的容器之间,以及容器和宿主机系统之间可以通过进程ID来相互访问和操作
pid: "host"
暴露端口信息
使用宿主:容器(host:container)格式,或者仅仅指定容器的端口(宿主机会随机选择端口)
ports:
- "3000"
- "8000:8000"
- "8000:80"
- "127.0.0.1:8000:8000"
指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)
例如,配置标签的用户名和角色名
security_opt:
- label:user:USER
- label:role:ROLE
指定应用停止时,容器的优雅停止期限。过期后则通过SIGKILL强制退出
默认为10s
指定停止容器的信号,默认为SIGTERM
配置容器内的内核参数
例如,指定连接数为4096和开启TCP的syncookies:
sysctls:
net.core.somaxconn: 4096
net.ipv4.tcp_syncookies: 1
指定容器的ulimits限制值
例如,只当最大进程数为65535,指定文件句柄数为20000(软限制)和40000(硬限制)
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
指定用户命名空间模式,例如使用主机上的命名空间
userns_mode: "host"
数据卷所挂载路径设置,可以设置宿主机路径(host:container)或加上访问限制(host:container:ro)
支持driver、driver_opts、external、labels、name等子配置
volumes:
# 在容器内部创建数据卷
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs:ro
# 使用创建的数据卷挂载到容器
- datavolume:/var/lib/mysql
指定重启策略,可以为no(不重启)、always(总是)、on-failure(失败时)、unless-stopped(除非停止)
例如,配置总是重启
restart: always
此外,还包括domainname、hostname、ipc、mac_address、privileged、read_only、shm_size、stdin_open、tty、user、working_dir等指令
指定容器中工作目录
working_dir: /code
指定容器中搜索域名、主机名、mac地址
domainname: your_website.com
hostname: abc
mac_address: 08-00-27-00-0A-0B
运行容器中运行一些特权命令
privileged: true
Compose命令的基本使用格式是
docker compose [OPTIONS] COMMAND
常用命令选项如下:
# build 构建(重新构建)项目中的服务容器
docker-compose build [options] [service...]
# config 校验和查看Compose文件的配置信息
docker-compose config [options]
-q: 值检验格式正确与否,不输出内容
--services:打印出Compose中所有的服务信息
--volumes:打印出Compose中所有的挂载信息
# down 停止服务栈,并删除相关资源,包括容器、挂载卷、网络、创建镜像等
docker-compose down [options]
-v:删除挂载的数据卷
-rmi:指定删除镜像的类型,包括all(所有镜像),local(仅本地)
# run 在指定服务上执行一个命令
docker-compose run [options] [-p Port...] [-e ...] service [command] [args]
例如:
docker-compose run web ping baidu.com
# start 启动已经存在的服务容器
docker-compose start [service...]
# stop 停止已经在运行的容器
docker-compose stop [options] [service...]
# events 实时监控容器的事件信息
docker-compose events [options] [service...]
# exec 在一个运行中的容器内执行给定命令
docker-compose exec [options] service command [args...
-d: 在后台运行命令
-e 设置环境变量
-u:以给定的用户身份执行命令
# help 获取命令帮助
docker-compose --help
# images 列出服务所创建的镜像
docker-compose images [options] [service...]
-q:仅显示镜像的ID
# kill 通过发送SIGKILL信号来强制停止容器
docker-compose kill [options] [service....]
# rm 删除所有停止状态的服务容器
docker-compose rm [options] [service...]
-f:强制删除
# logs 查看服务容器的输出
docker-compose logs [options] [service....]
-f:持续跟踪输出日志
-t:显示时间戳
# port 打印某个容器端口所映射的公共端口
docker-compose port [options] service private_port
# ps 列出项目中目前的所有容器
docker-compose ps [options] [service....]
# pull 拉取服务依赖的镜像
docker-compose pull [options] [service...]
# push 推送服务创建的镜像到镜像仓库
docker-compose push [options] [service...]
# restart 重启项目中的服务
docker-compose restart [options] [service...]
# scale 设置指定服务运行的容器个数
docker-compose scale [options] [service=NUM...]
通过service=num的参数来设置数量,例如:
docker-compose scale web=3 db=2
# top 显示服务栈正在运行的进程信息
docker-compose top [service...]
# pause 暂停一个服务容器
docker-compose pause [service...]
# unpause 恢复处于暂停状态的服务
docker-compose unpasue [service...]
# up 该命令十分强大,它将尝试自动完成包括构建镜像,创建服务,启动服务,并关联服务相关容器的一系列操作
默认情况下 docker-compose up 启动容器都在前台
控制台将会同时打印所有容器的输出信息 ctrl + c 可以停止命令 所有容器将会停止
如果使用 docker-compose up -d 获奖会在后台启动并运行所有容器。 <-- 一般会使用这种
如果容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建
(1)首先创建一个干净的目录
[root@docker ~]# mkdir nginx-web
[root@docker ~]# cd nginx-web/
(2)准备需要的文件
[root@docker nginx-web]# ls
nginx.conf
[root@docker nginx-web]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
upstream colony {
server tomcat1:8080 weight=5;
server tomcat2:8080 weight=5;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://colony;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
(3)编写Dockerfile-nginx
[root@docker nginx-web]# vim Dockerfile-nginx
FROM centos:7.9.2009
MAINTAINER CSQ
RUN yum install -y epel-release && yum install -y nginx
ADD nginx.conf /etc/nginx/nginx.conf
RUN /bin/bash -c 'echo init ok'
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
(4)编写Dockerfile-tomcat
[root@docker nginx-web]# vim Dockerfile-tomcat
FROM centos:7.9.2009
MAINTAINER CSQ
RUN mkdir -p /docker_home/local
ADD tomcat /docker_home/local/tomcat8.0
ADD jdk1.8.0_144 /docker_home/local/java18
ENV JAVA_HOME /docker_home/local/java18
ENV TOMCAT_HOME /docker_home/local/tomcat8.0
ENV PATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin
EXPOSE 8080
CMD ["/docker_home/local/tomcat8.0/bin/catalina.sh","run"]
(5)编写docker-compose文件
[root@docker nginx-web]# vim docker-compose.yaml
version: '3'
services:
nginx:
restart: always
image: nginx:v1.0
container_name: nginx
ports:
- "8888:80"
depends_on:
- tomcat1
- tomcat2
tomcat1:
image: tomcat1:v1.0
container_name: tomcat1
hostname: tomcat2
volumes:
- /htmltomcat1:/docker_home/local/tomcat8.0/webapps/ROOT
ports:
- "8081:8080"
tomcat2:
image: tomcat2:v1.0
container_name: tomcat2
hostname: tomcat2
volumes:
- /htmltomcat2:/docker_home/local/tomcat8.0/webapps/ROOT
ports:
- "8082:8080"
(6)运行容器
[root@docker nginx-web]# docker-compose up -d
[+] Running 4/4
✔ Network nginx-web_default Created 0.4s
✔ Container tomcat2 Started 0.0s
✔ Container tomcat1 Started 0.0s
✔ Container nginx Started 0.0s
(7)写入tomcat1 和tomcat2的站点文件
[root@docker nginx-web]# vim /htmltomcat1/index.html
<h1><b>tomcat1 8081</b></h1>
[root@docker nginx-web]# vim /htmltomcat2/index.html
<h1><b>tomcat2 8082</b></h1>
(8)浏览器访问,可以多刷新几次观察访问到那个tomcat节点上了