Docker Dockerfile Docker-compose学习笔记

文章目录

Centos环境下安装Docker

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

Windows环境下安装Docker

安装Docker需要保证你的电脑开启虚拟化

进入任务管理器→点击性能→看一下CPU是否开启虚拟化

启用Hyper-v

打开控制面板→程序→启动或关闭Windows功能→找到Hyper-V打上√

  1. 下载exe文件

下载地址:https://www.docker.com/products/docker-desktop/

  1. 双击下载的exe文件

image-20230811113909177

  1. 安装成功,点击Close关闭安装界面

image-20230811160240179

  1. 此时桌面图标会员Docker Desktop,双击它,点击Accept

image-20230811160332425

如果打开后提升启动出现问题,需要安装wsl内核更新包wsl_update_x64

下载完后双击安装即可

  1. 安装成功

image-20230811164550357

  1. 打开CMD测试一下是否能够拉取镜像

Docker的版本

image-20230811164643739

拉取镜像

image-20230811164827296

image-20230811164913463

运行拉取的镜像

image-20230811165006051

设置暴露的端口,和容器名

image-20230811165103592

image-20230811165242317

image-20230811165259163

配置镜像源

默认官方源因为网络原因比较慢,我们使用阿里云的镜像源

image-20230811170458660

自己注册一个阿里云,搜索容器镜像服务→镜像工具→镜像加速器,即可获取加速地址,然后填入如下内容框即可。

image-20230811171834590

使用Dokcer镜像

Docker运行容器前需要存在对应的镜像,如果镜像不存在,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub仓库),用户也可以通过配置,使用自定义的镜像仓库。

1.获取镜像

官方的Docker Hub网站已经提供了数十万个镜像供大家下载,只需要使用pull命令,既可以拉取Docker Hub中的镜像。

docker [image] pull命令直接从Docker Hub 镜像源来下载镜像。该命令格式为docker [image] pull <Name[:TAG]>

  • NAME:镜像仓库的名称
  • TAG:是镜像的标签(通常用来显示版本信息)

pull子命令主要包括有:

  • -a:是否获取仓库中所有镜像
  • -q:不输出拉取的详细信息

例如,获取一个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

如果从非官方仓库下载,则需要在仓库名称前指定完整的仓库地址

2.查看镜像信息

(1)列出镜像

使用docker images 或者 docker image ls命令可以列出本地主机上已有镜像

docker images 子命令主要包括:

  • -a:列出所有镜像文件
  • -q:输出ID信息

例如,列出上一小节所获取的镜像

[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:镜像大小

(2)镜像标签

为了使用特定的镜像,还可以使用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来表示这个镜像

(3)镜像详细信息

使用docker [image] inspect命令可以获取镜像的详细信息

docker inspect 子命令主要包括:

  • -f :指定输出信息
  • -s :如果类型为容器,则显示文件的总大小

例如,查看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}

(4)镜像历史

docker history 该命令就是查看镜像各层的创建信息

docker history 子命令主要包括:

  • -q:输出镜像各层的ID

例如,查看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    

3.搜索镜像

使用docker search命令可以搜索 Docker Hub官方仓库中的镜像。

docker search子命令主要包括:

  • -f:过滤输出内容
  • –limit:限制输出结果个数,默认为25个

例如,搜索官方提供的带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]

4.删除和清理镜像

(1)使用标签删除镜像

使用docker rmidocker image rm 命令可以删除镜像

docker rmi 支持的子命令包括:

  • -f:强制删除镜像,即使有容器依赖他
  • –no-prune:表示不移除本地存储的父镜像

例如,要删掉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
# 用该命令删除只有一个标签的镜像
# 就会删除这个镜像文件的所有文件层

(2)使用ID删除镜像

当使用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

(3)清理镜像

使用Docker一段时间后,系统可能会遗留一些临时镜像,以及一些没有被使用的镜像,可以通过 docker image prune命令来进行清理

子命令包括:

  • -a:删除所有无用镜像
  • -f:强制删除镜像,不进行提示

例如,如下命令会自动清理临时遗留镜像文件层,最后会提示释放的存储空间

[root@docker ~]# docker image prune  -f
Total reclaimed space: 0B

5.创建镜像

创建镜像的方法主要有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建

(1)基于已有容器创建

使用docker [container] commit 命令

子命令主要包括:

  • -a:作者信息
  • -c:提交的适合指向Dcokerfile指令,包括CMD | ENTRYPOINT | ENV|EXPOSE | LABEL | ONBUILD|USER | VOLUME | WORKDIR 等
  • -m:提交信息
  • -p:提交时暂停容器运行

首先,启动一个镜像,并在其中进行修改操作。例如,创建一个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

(2)基于本地模板导入

用户也可以直接从一个操作系统模板文件导入一个镜像,主要使用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

(3)基于Dockerfile创建

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 "<b>Hello Docker!</b>" > /html/index.html

image-20230812001834353

6.存出和载入镜像

(1)存出镜像

如果要到处镜像到本地文件,可以使用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 文件将该镜像分享给其他人

(2)载入镜像

可以使用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 
# 都是可以的

7.上传镜像

可以使用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

image-20230812084402834

第一次上传,会提示输入登录信息,之后登录信息会记录到本地~/.docker目录下

操作Docker容器

容器可以看作是镜像的一个实例,它包含了镜像的所有内容以及运行时需要的可写文件层。镜像是一个静态的只读文件,类似于一个应用程序的安装包,而容器则是在镜像的基础上创建的一个可运行的实例。在容器中,我们可以启动、停止、暂停、删除应用程序,并且容器中的应用程序处于运行状态,可以接收请求并与其他容器或主机进行通信。容器的隔离性使得应用程序之间相互独立,互不影响,同时容器的快速启动和高效利用资源的特点使得应用程序的部署和管理更加方便和高效。

1.创建容器

(1)新键容器

可以使用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

(2)启动容器

使用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

(3)新建并启动容器

除了创建容器后通过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 也可以退出容器

(4)阻塞容器打印错误代码

可以使用docker container wait CONTAINER [CONTAINER…]子命令来等待容器退出,并打印退出返回结果

某些适合,执行docker [container] run时候因为命令无法正常执行容器会出错 直接退出,此时可以查看退出的错误代码

  • 125:Docker daemon执行出错,例如指定了不支持的Docker 命令参数
  • 126:所指定命令无法执行,例如权限出错
  • 127:容器内命令无法找到

例如,运行一个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,表示容器内命令无法找到
# 利用这个方法可以快速定位错误

(5)查看容器输出

获取容器的输出信息,可以通过docker [container] logs 命令

子命令主要包括:

  • -f:持续保持输出
  • -t:显示时间戳信息

例如查看之前运行hello world的容器输出信息

[root@docker ~]# docker logs b97e34231055
hello world

2.停止容器

(1)暂停容器

使用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

(2)终止容器

使用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信号来强行终止容器

(3)重启容器

使用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

3.进入容器

(1)attach命令

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到同一个容器中,所有窗口都会同步显示输出命令的信息,当某个窗口因为某些命令阻塞时,其他窗口就无法执行操作了。

(2)exec命令

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终端,不影响容器内其他应用的前提下,用户可以与容器进行交互

4.删除容器

使用docker [container] rm命令来删除处于终止或退出状态的容器

主要的命令包括:

  • -f:强制删除一个运行中的容器
  • -l:删除容器的连接,但保留容器
  • -v:删除容器挂载的数据卷

例如,查看处于终止状态的容器,并删除

[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

5.导入和导出容器

(1)导出容器

导出容器是指,导出一个已经创建的容器到一个文具,不管此时这个容器是否处于运行状态。可以使用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

(2)导入容器

使用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

6.load和import区别

  • 如果需要导入整个镜像,包含镜像的完整文件系统、元数据和历史记录,则使用 docker load 命令。

  • 如果只需要导入容器的文件系统不包含容器的元数据和历史记录,则使用 docker import 命令。

7.查看容器

(1)查看容器详情

使用 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
                }
            }
        }
    }
]

(2)查看统计信息

查看统计信息可以使用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

(3)查看容器内进程

使用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

8.其他容器命令

(1)复制文件

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

(2)查看变更

docker [container] diff 查看容器内文件系统的变更

例如,查看web容器内的数据修改

[root@docker ~]# docker diff web
C /tmp
A /tmp/html
A /tmp/html/index.html

输出的每一行都以一个字符开头,表示不同类型的变化:

  • A:表示新增的文件或目录
  • C:表示改变了文件或目录的权限或属性
  • D:表示删除的文件或目录

(3)查看端口映射

使用docker [container] port命令可以查看容器的端口映射情况

例如,查看web容器的端口映射情况

[root@docker ~]# docker port web
80/tcp -> 0.0.0.0:9999
80/tcp -> [::]:9999

(4)更新配置

使用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,

9.容器运行常用相关参数

选项 说明
-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=[ ] 指定网络模式

10.容器环境配置常用参数

选项 说明
-e 指定容器内的环境变量
–link [name:alias] 链接到其他容器
–name 指定容器别名

搭建本地私有仓库

1.使用registry镜像创建私有仓库

可以通过官方提供的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"]}

image-20230812165100583

(6)列出私有仓库的centos镜像有哪些tag

[root@docker ~]# curl http://192.168.200.10:5000/v2/centos/tags/list
{
    
    "name":"centos","tags":["v1.0"]}

image-20230812165316368

==(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

2.部署harbor仓库

是什么

Harbor是一个企业级镜像仓库项目,由VMware开源,每个组件以Docker容器的形式构建,通过Docker-compose进行快速部署

为什么

虽然有很多Docker公共镜像仓库,但是从安全和效率等方面考虑,部署私有镜像仓库是非常必要的:

  • 安全:如果没有自己的镜像仓库,自己构建的镜像上传到第三方镜像仓库,则无形中增加了泄露的风险
  • 效率:如果没有自己的镜像仓库,每次通过外网从第三方镜像仓库下载镜像,下载速度缓慢,影响工作效率

(1)环境部署

(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

(2)搭建harbor仓库

(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

(3)安装完成

状态:docker-compose ps

停止:docker-compose down

启动: docker -compose up -d

(4)访问

启动浏览器→访问https://192.168.200.20

账户:admin

密码:刚刚配置文件设置的密码

image-20230813110906796

(5)上传镜像

(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

image-20230813113021874

(6)拉取harbor仓库的镜像

# 先删除之前的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

Docker数据管理

容器中的管理数据主要有两种方式:

  • 数据卷:容器内数据直接映射到本地主机环境
  • 数据卷容器:使用特定容器维护数据卷

1.数据卷

数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似Linux的mount

数据卷有哪些特性?

  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便
  • 数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作
  • 数据卷的更新不会影响镜像
  • 卷会一直存在,直到没有容器使用

(1)创建数据卷

使用docker volume来管理数据卷,如下命令可以创建一个数据卷

# 创建数据卷
[root@docker ~]# docker volume create -d local test
# 查看你数据卷位置
[root@docker ~]# ls -l /var/lib/docker/volumes/
drwx-----x. 3 root root     19 813 21:55 test

除了create命令之外,docker volume 还支持inspect(查看详细信息)、ls(列出已有数据卷)、prune(清理无用数据卷)、rm(删除数据卷)等

(2)绑定数据卷

出了可以用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 "<html><body><h1>I am ChenShiRen</h1></body></html>" > 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 

浏览器访问

image-20230813224059217

接下来使用一下bind数据卷类型绑定数据卷,bind其实跟 -v 这个参数使用效果是一样的,但是这样挂载的数据卷不好管理,docker volume ls 是查不到的

# 先创建挂载目录
[root@docker ~]# mkdir /web
# 写入站点文件
[root@docker ~]# echo "<html><body><h1>I am CSR</h1></body></html>" > /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

浏览器访问

image-20230813225600157

需要注意的是本地目录的路径必须是绝对路径,容器内的路径可以是相对路径,如果目录不存在,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 "<b>i am csr</b>" > /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

浏览器访问也是没有问题的

image-20230813233643240

2.数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器

首先将本地数据卷/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 参数所挂载数据卷的容器自身并不需要保持在运行状态

3.利用数据卷容器来迁移数据

可以利用数据卷容器对其中的数据进行备份、恢复,以实现数据卷迁移

(1)备份

使用如下命令备份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

(2)恢复

如何恢复呢,使用如下命令,将数据恢复到另一个容器内的/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端口映射与容器互联

在实践中经常会碰到需要多个服务组件共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。

Docker出了通过网络访问外,还提供了两个很方便的功能来满足服务访问的基本需求:一个是运行映射容器内应用的服务端口到本地宿主机;另一个是互联机制实现多个容器间通过容器名来快速访问。

1.端口映射实现容器访问

(1)从外部访问容器应用

在启动容器时需要指定对应的参数,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的

当容器中运行一些网络应用时,要让外部访问这些应用时,可以通过 -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界面

image-20230814094622637

-p(小写) 则可以指定映射的端口,并且,在一个指定端口上只可以绑定一个容器。

支持的格式有 IP:HostPort:ContainerPort | IP::ContainerPort | HostPort:ContainerPort

(2)映射所有接口地址

可以使用 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 "<h1><b>Many Port NGINX</b></h1>" > /nginxhtml/index.html 

80端口

image-20230814104653472

9000端口

image-20230814104707314

8000端口

image-20230814104719874

(3)映射到指定地址的指定端口

可以使用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

(4)映射到指定地址的随机端口

使用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

(5)查看映射端口配置

使用docker port 来查看当前映射的端口配置

[root@docker ~]# docker port ip_nginx2 9000
192.168.200.10:32769

容器有自己的网络和IP,使用docker inspect 容器ID 可以获取容器的具体信息

2.互联机制实现便捷互访

容器的互联是一种让多个容器中的应用镜像快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体IP地址。

(1)自定义容器命名

连接系统依据容器的名称来执行。首先需自定义一个好记的容器名。

使用–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

(2)容器互联

使用 --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通过两种方式为容器公开连接信息

  • 更新环境变量
  • 更新 /etc/hosts文件

使用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来快速创建自定义的镜像。

1.指令说明

Dockerfile中的指令一般格式为 【指令 参数】的形式

配置指令

指令 说明
ARG 定义创建镜像过程中使用的变量
FROM 指定所创建镜像的基础镜像
LABEL 为生成的镜像添加元数据标签信息
EXPOSE 声明镜像内服务监听的端口
ENV 指定环境变量
ENTRYPOINT 指定镜像的默认入口命令
VOLUME 创建一个数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像时指定自动执行的操作指令
STOPSIGNAL 指定退出的信号值
HEALTHCHECK 配置所启动容器如何进行健康检查
SHELL 指定默认shell类型

操作指令

指令 说明
RUN 运行指定命令
CMD 启动容器时指定默认执行的命令
ADD 添加内容到镜像
COPY 复制内容到镜像

(1)配置指令

ARG

定义创建镜像过程中使用的变量

格式为ARG <name>[=<default value>]

例如,使用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

指定所创建镜像的基础镜像

常用格式为 FROM <image>:<tag>

任何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指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像

格式为LABEL <key>=<value> <key>=<value> <key>=<value> ....

例如:

[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

指定镜像内服务监听的端口

格式为 EXPOSE <port> [<port>/<protocol>...]

该指令只是声明作用,并不会自动完成端口映射

如果需要映射,需要在启动容器的时候使用 -P 参数或 -p 参数

ENV

指定环境变量,在镜像生成过程中会被使用,在镜像启动后的容器中也会存在

格式为 ENV <key> <value> 或者 ENV <key>=<value>...

例如:

[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

指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数

支持两种格式:

  • ENTRYPOINT ["echo", "Hello, World!"] :exec 调用执行
  • ENTRYPOINT command param1 param2 ... :shell中执行

如果在Dockerfile中使用了多个ENTRYPOINT指令,只有最后一个指令会生效

VOLUME

创建一个数据卷挂载点,VOLUME指令允许开发者定义一个或多个目录,用于在容器中存储持久化数据或与宿主机共享文件

格式为 VOLUME ["/data",/path/aaa]

可以指定多个路径,每个路径都会在容器中被创建为一个挂载点。

USER

指定运行容器时的用户名或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

指定工作目录

格式为 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

指定当基于所生成镜像创建子镜像时,自动执行的操作命令

格式为 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

image-20230815120135182

STOPSIGNAL

指定创建镜像启动的容器接收退出的信号值:

STOPSIGNAL signal

HEALTHCHECK

配置所启动容器如何进行健康检查(如何判断健康与否)

格式有两种:

  • HEALTHCHECK [OPTIONS] CMD command:根据所执行命令返回值是否为0来判断
  • HEALTHCHECK NODE:禁止基础镜像的健康检查

OPTION支持如下参数:

  • –interval= :过多久检查一次
  • –timeout= :每次检查等待结果的超时
  • –retries= :如果失败了,重试几次才最终确定失败

SHELL

SHELL指令在Dockerfile中用于设置容器的默认shell。它允许我们指定在容器中执行命令时使用的默认shell。

默认值为 SHELL["/bin/sh", "-c"]

(2)操作指令

RUN

RUN指令运行指定命令

常用格式为 RUN <command>

每条RUN指令将再当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长可以使用 \ 来换行

例如:

RUN sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config && \
    setenforce 0 && \
    systemctl stop firewalld && \
    systemctl disable firewalld

CMD

CMD指令用来指定启动容器时默认执行的命令

格式:

  • CMD ["echo", "Hello, World!"]:相当于执行 echo Hello World!
  • CMD echo "Hello, World!:在默认的Shell执行,提供给需要交互的应用

ADD

添加内容到镜像

格式为 ADD <src> <dest>

该目录将复制本机路径下的内到容器中的路径下

其中可以是Dockerfile所在目录的相对路径;也是一个URL;还可以是tar文件(自动解压为目录) 可以是绝对路径,或者是相对于工作目录(WORKDIR)的相对路径

COPY

复制内容到镜像

格式为 COPY

复制本机文件或目录到镜像中的中。目标路径不存在时,会自动创建

(3)CMD和ENTRYPOINT区别

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参数,但是找不到这个参数所以报错了

(4)COPY和ADD的区别

# 准备测试文件
[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 会原封不动的将文件传输到容器中

2.创建镜像

编写完成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 .

(1)命令选项

构建镜像的常用命令选项

选项 说明
-f Dockerfile名称
-m 限制使用内存量
–network 指定网络模式
-q 不打印创建过程中的日志信息
-t 指定镜像标签

(2)选择父镜像

生成新的镜像都需要通过FROM指令来指定父镜像。父镜像是生成镜像的基础,会影响到所生成镜像的大小和功能

用户可以选择两种镜像作为父镜像,一种是所谓的基础镜像,另一种是普通镜像(第三方镜像)

(3).dockerignore

在Docker中,可以使用.dockerignore文件来指定在构建镜像时需要忽略的文件和目录。

支持以下几种模式:

  • " * "表示任意多个字符
  • " ? "表示单个字符
  • " ! "表示不匹配(即不忽略指定路径或文件)

注意事项:

  • .dockerignore文件需要与Dockerfile文件位于同一目录下
  • .dockerignore文件中的每一行表示一个匹配规则

(4)多步骤创建

Docker多步骤创建是一种构建Docker镜像的技术,它通过多个构建阶段(步骤)来分解复杂的构建过程,以减小最终镜像的体积。

多步骤创建的主要优点有:

  1. 减小镜像体积:通过分解构建过程并在每个阶段中只保留必要的文件和操作,可以减小最终构建的镜像的体积。这对于减少镜像下载和传输的时间非常有帮助。

  2. 提高安全性:多步骤创建可以确保最终的Docker镜像中只包含必要的文件和配置,减少了潜在的安全风险。

  3. 提高构建速度:通过将构建过程分解为多个阶段,可以重用已构建的中间镜像,从而加快构建速度。

以C语言应用为例

创建main.c文件,内容为:

#include <stdio.h>
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!

Web服务与应用

Apache

Apache是一个开源的、跨平台的Web服务器软件,全称为Apache HTTP Server。它是目前互联网上最流行的Web服务器之一,广泛应用于各种网站和Web应用的搭建和部署中。 Apache最初由美国国家超级计算应用中心(NCSA)开发,后来由于其开源的特性,吸引了全球范围内的开发者参与到项目中,逐渐发展成为一个独立的、由Apache软件基金会管理的项目。Apache软件基金会是一个非营利性的组织,致力于支持和发展开源软件项目。

使用DockerHub镜像

(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

浏览器访问

image-20230818135132142

也可以不创建自定义镜像,直接通过映射目录方式运行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 "<h1><b>Centos:7.9.2009  Apache</b></h1>" >> 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)浏览器访问

image-20230818141202004

Nginx

Nginx(发音为"engine-x")是一个高性能的开源Web服务器和反向代理服务器。它的设计目标是提供高性能、高并发的服务,并具备良好的可扩展性和稳定性。Nginx以其卓越的性能和灵活的配置而受到广泛的关注和使用。

使用DockerHub镜像

直接使用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

image-20230818165157287

自定义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 

image-20230818171551516

也可以用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

浏览器访问

image-20230818172845910

使用自定义镜像

[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

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

编写Dockerfile脚本

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

浏览器访问

image-20230818181128074

数据库应用

MySQL

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

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"

使用Dockerfile自定义配置

[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客户端

image-20230818194053225

image-20230818194309172

Docke-compose容器编排

Docker-compose是Docker官方开源的项目,负责实现对基于Docker容器多应用服务的快速编排。功能上有点类似于Openstack 的 Heat模板

Docker-compose是一个用于定义和管理多容器Docker应用程序的工具,前面学习Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在工作中经常会碰到需要多个容器相互配合来完成某项任务。例如实现一个Web项目,除了web服务本身还需要数据库服务,nginx服务等,docker-compose满足了这样的需求,它允许用户通过一个单独的docker-compose.yaml模板文件来定义一组相关联的应用容器

1.安装与卸载

(1)pip安装

# 安装  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

image-20230816113201367

解决方法

  wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
  python get-pip.py
  pip install --upgrade setuptools

(2)二进制包安装

下载地址: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

(3)卸载

# 如果是二进制包的方式安装的,删除二进制文件即可
[root@docker ~]# rm -rf /usr/local/bin/docker-compose 
# 如果是pip工具安装的,执行如下命令删除
[root@docker ~]# pip uninstall docker-compose

2.Compose模板文件

(1)指令说明与配置

模板文件是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

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

image1image2等是已存在的镜像名称或镜像标签。可以指定多个缓存来源,以便在构建过程中重用这些镜像的缓存层。

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,cap_drop

添加或删除容器功能

# 让容器拥有所有能力可以指定为:
cap_add:
  - ALL

# 去掉NET_ADMIN和SYS_ADMIN能力可以指定为:
cap_drop:
  - NET_ADMIN
  - SYS_ADMIN

command

覆盖容器启动后默认执行的命令

可以为字符串格式

command: echo "hello Docker"

或者JSON数据格式

command: ["bash", "-c", "echo", "hello Docker"]

cgroup_parent

指定父cgroup组,意味着将继承该组的资源限制

例如,创建了一个cgroup组名称为cgroups_1

cgroup_parent: cgroups_1

container_name

指定容器名称

container_name: my-web:v1.0

需要注意的是指定容器名称后,该服务将无法进行扩展,因为Docker不允许多个容器实例重名

devices

指定设备映射关系

devices:
  - "/dev/ttyUSB1:/dev/ttyUSB0"

depends_on

指定多个服务之间的依赖关系。启动时,会先启动被依赖服务,例如,可以指定依赖于db服务

denpends_on: db

dns

自定义DNS服务器。可以是一个值,也可以是一个列表

dns: 8.8.8.8
dns: 
  - 8.8.8.8
  - 114.114.114.114

dns_search

配置DNS搜索域。可以是一个值,也可以是一个列表

dns_search: example.com
dns_search:
  - domain1.example.com
  - domain2.example.com

dockerfile

如果需要,指定额外的编译镜像的Dockerfile文件,可以通过该指令来指定,例如

dockerfile: Dockerfile-abc

该指令不可以和image同时使用,否则Compose将不知道根据哪个指令来生成最终的服务镜像

entrypoint

覆盖容器中默认的入口命令

entrypoint: python app.py

env_file

从文件中获取环境变量,可以为单独的文件路径或列表。如果有变量名称与environment指令冲突,则以后者为准

env_file: .env
env_file:
   - ./common.env
   - ./root/web.env
   - ./opt/abc.env

环境变量文件中每一行必须符合格式,支持#开头的注释行

# Set Rails/Rack environment
RACK_ENV=development

environment

设置环境变量,可以使用数组或字段两种格式。只要给定名称的变量会自动获取运行Compose主机上对应变量的值,可以用来防止泄露不必要的数据

environment:
  MYSQL_ROOT_PASSWORD: root

或者

environment:
 - MYSQL_ROOT_PASSWORD=root

注意,如果变量名称或者值中用到 true|false ,yes|no 等表达布尔含义的词汇,最好放到引号里面,避免YAML自动解析某些内容为对应的布尔语义

https://yaml.org/type/bool.html 中给定了这些特定的词汇,包括

image-20230817093505451

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数,如下所示

expose:
 - "3000"
 - "9000"

extends

基于其他模板文件进行扩展。例如,我们已经有了一个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

浏览器访问

image-20230817101446558

后者会自动继承common.yaml中的myweb服务及环境变量定义。使用extends需要注意下面两点:

  • 避免循环依赖,例如A依赖B,B依赖C,C依赖A的情况
  • extends不会继承links和volumes_from中定义的容器和数据卷资源

一般情况下,基础模板定义一些共享镜像和环境变量,在扩展模板中具体指定应用变量、链接、数据卷等信息

external_links

链接到docker-compose.yaml 外部的容器,并非Compose管理的外部容器也可以链接

例如

services:
  myservice:
    image: myimage
    external_links:
      - external_container_name:alias

extra_hosts

类似Docker中的 --add-host参数,指定额外的host名称映射信息

extra_hosts:
  - "chenshiren:8.8.8.8"

会在启动后的服务容器中 /etc/hosts文件中添加如下内容

8.8.8.8 chenshiren

healthcheck

指定检测应用监控状态的机制,包括检测方法(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

image

指定镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取这个镜像

image: ubuntu
image: f0b4b9abdf1d

isolation

配置容器隔离的机制,包括 default、process和hyperv

labels

为容器添加Docker元数据信息。例如可以为容器添加辅助说明信息

labels:
   mantainer: csq
   release: v1.0

links

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

跟日志相关的配置,包括一系列的子配置

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

设置网络模式

network_mode: "none"
network_mode: "bridge"
network_mode: "host"

networks

所加入的网络。需要在顶级的networks字段中定义具体的网络信息

例如,创建一个自定义网络并将多个服务容器连接到该网络

version: '3'
services:
  web:
    image: nginx
    networks:
      - mynetwork
  db:
    image: mysql
    networks:
      - mynetwork
networks:
  mynetwork:
    driver: bridge

pid

跟主机系统共享进程命名空间。打开该选项的容器之间,以及容器和宿主机系统之间可以通过进程ID来相互访问和操作

pid: "host"

ports

暴露端口信息

使用宿主:容器(host:container)格式,或者仅仅指定容器的端口(宿主机会随机选择端口)

ports:
  - "3000"
  - "8000:8000"
  - "8000:80"
  - "127.0.0.1:8000:8000"

security_opt

指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)

例如,配置标签的用户名和角色名

security_opt:
  - label:user:USER
  - label:role:ROLE

stop_grace_period

指定应用停止时,容器的优雅停止期限。过期后则通过SIGKILL强制退出

默认为10s

stop_signal

指定停止容器的信号,默认为SIGTERM

sysctls

配置容器内的内核参数

例如,指定连接数为4096和开启TCP的syncookies:

sysctls:
  net.core.somaxconn: 4096
  net.ipv4.tcp_syncookies: 1

ulimits

指定容器的ulimits限制值

例如,只当最大进程数为65535,指定文件句柄数为20000(软限制)和40000(硬限制)

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

userns_mode

指定用户命名空间模式,例如使用主机上的命名空间

userns_mode: "host"

volumes

数据卷所挂载路径设置,可以设置宿主机路径(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

restart

指定重启策略,可以为no(不重启)、always(总是)、on-failure(失败时)、unless-stopped(除非停止)

例如,配置总是重启

restart: always

(2)其他指令

此外,还包括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

3.Compose命令说明

Compose命令的基本使用格式是

docker compose [OPTIONS] COMMAND

常用命令选项如下:

  • -f:指定使用的Compose模板文件,默认为docker-compose.yaml
  • -p:指定项目名称,默认将使用所在目录名称作为项目名
  • -v:打印版本信息

(1)Compose命令使用说明

# 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 将会尝试停止容器,然后重新创建

4.Compose应用案例(一):nginx负载均衡

(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节点上了

image-20230818124722213

image-20230818124813313

猜你喜欢

转载自blog.csdn.net/qq_52089863/article/details/132368248