# Docker

# Docker介绍

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker主要由仓库,镜像,容器这3个大的核心组成。

# 仓库

Docker仓库(Repository)类似于代码仓库,是Docker集中存放镜像文件的场所。根据所存储的镜像公开分享与否,Docker仓库可以分为公开仓库(Public)以及私有仓库(Private)两种。
目前,最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库保护Docker Pool等,可以提供稳定的国内访问。

# 镜像

Docker镜像(Image)类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统。
例如,一个镜像可以只包含一个完整的CentOS操作系统,可以把它理解为一个CentOS镜像。镜像也可以由安装了其他服务的操作系统组成,如安装了MySQL服务的镜像,我们称它为MySQL镜像。
镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的镜像,并通过简单的命令就可以直接使用。

# 容器

Docker容器(Container)类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。
容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而这些容器都是相互隔离、互不可见的。

# 镜像

# 搜寻镜像

使用docker search指令可以从镜像仓库搜索需要的镜像。

[root@VM-8-5-centos ~]# docker search mysql
# 一般我们使用官方镜像,如果使用非官方镜像的话,最好使用支持AUTOMATED的镜像,我们可以自己验证镜像的来源和内容。
# 镜像名称                      # 镜像描述                                       #镜像受欢迎程度 
NAME                            DESCRIPTION                                     STARS               
# 是否官方镜像       #是否自动构建,自动构建的镜像允许用户验证镜像的来源和内容。
OFFICIAL            AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   14828               [OK]
mariadb                         MariaDB Server is a high performing open sou…   5664                [OK]
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   940                 [OK]
percona                         Percona Server is a fork of the MySQL relati…   624                 [OK]
databack/mysql-backup           Back up mysql databases to... anywhere!         107
bitnami/mysql                   Bitnami MySQL Docker Image                      106                                     [OK]
ubuntu/mysql                    MySQL open source fast, stable, multi-thread…   58
linuxserver/mysql-workbench                                                     55
linuxserver/mysql               A Mysql container, brought to you by LinuxSe…   41
rapidfort/mysql                 RapidFort optimized, hardened image for MySQL   25
google/mysql                    MySQL server for Google Compute Engine          25                                      [OK]

# 获取镜像

可以通过docker pull指令从镜像仓库中拉取镜像(一般我们会指定镜像的版本,如果没有指定的话,docker会拉取最新版本的镜像)。

[root@VM-8-5-centos ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
20e4dcae4c69: Pull complete
1c56c3d4ce74: Pull complete
e9f03a1c24ce: Pull complete
68c3898c2015: Pull complete
6b95a940e7b6: Pull complete
90986bb8de6e: Pull complete
ae71319cb779: Pull complete
ffc89e9dfd88: Pull complete
43d05e938198: Pull complete
064b2d298fba: Pull complete
df9a4d85569b: Pull complete
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

# 查看镜像

使用docker images指令可以查看Docker中现有的镜像。

[root@VM-8-5-centos ~]# docker images
#镜像来源于哪个仓库  #版本号              #镜像id             #创建时间(本地)      #镜像大小
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 5107333e08a8        8 weeks ago         501MB
nginx               1.25.1              89da1fb6dcb9        6 months ago        187MB
查看镜像的详细信息

使用docker inspect指令可以查看镜像的详细信息。

[root@VM-8-5-centos ~]# docker inspect 5107333e08a8
[
    {
        "Id": "sha256:5107333e08a87b836d48ff7528b1e84b9c86781cc9f1748bbc1b8c42a870d933",
        "RepoTags": [
            "mysql:5.7"
        ],
        "RepoDigests": [
            "mysql@sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb"
        ],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2023-12-12T19:11:08Z",
        "Container": "",
        "ContainerConfig": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null,
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "3306/tcp": {},
                "33060/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.16",
                "MYSQL_MAJOR=5.7",
                "MYSQL_VERSION=5.7.44-1.el7",
                "MYSQL_SHELL_VERSION=8.0.35-1.el7"
            ],
            "Cmd": [
                "mysqld"
            ],
            "ArgsEscaped": true,
            "Image": "",
            "Volumes": {
                "/var/lib/mysql": {}
            },
            "WorkingDir": "",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 501392011,
        "VirtualSize": 501392011,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/a99293270b57a3a4dbc8eb3535db0b8461f20cd68db220225770e7e01d8594a6/diff:/var/lib/docker/overlay2/04652fedcaaaa28035810365eb6c54d73c1c44aad6fa5dcfd990767866e80b3a/diff:/var/lib/docker/overlay2/0f108e1c2c8c43a5b9124702df9b79380509287e14c8ea4757a8b91609b0b7ef/diff:/var/lib/docker/overlay2/8f334d04a30b22626b48f83c2f0cf90ff93de75571412b23a8dde0486a0c8919/diff:/var/lib/docker/overlay2/4688ab0563e1894673c24ac7dad9cba22fbad801eec1c8ae3598c0fc9e6ac9cc/diff:/var/lib/docker/overlay2/4cf119c1edf78519364a10171a6e88ffe282454967672293b0c247ff5f6d6c4e/diff:/var/lib/docker/overlay2/7b22e8652f4bf8c839804bbac3957d1b8d2b8d36180e0a5914060cda4079e0f5/diff:/var/lib/docker/overlay2/78203efeac7da2b228b3052bd0f39da1b2a8cb5b3c48b6b60dd274b734d9de3a/diff:/var/lib/docker/overlay2/3c02c5e326e39fb1d7634e158c5a3068b7a87fddd505e3f892530b481e1c6c54/diff:/var/lib/docker/overlay2/fe990a8a60616df7c7331a215f505a519bb5fd90df1551397ecff99147204adb/diff",
                "MergedDir": "/var/lib/docker/overlay2/b58e58ec4d6f6faaf84b7a6fd7dcebbfc9582dd4b8d64e6a674ee773973f71ea/merged",
                "UpperDir": "/var/lib/docker/overlay2/b58e58ec4d6f6faaf84b7a6fd7dcebbfc9582dd4b8d64e6a674ee773973f71ea/diff",
                "WorkDir": "/var/lib/docker/overlay2/b58e58ec4d6f6faaf84b7a6fd7dcebbfc9582dd4b8d64e6a674ee773973f71ea/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:cff044e186247f93aa52554c96d77143cc92f99b2b55914038d0941fddeb6623",
                "sha256:7ff7abf4911b44c1b705de478892bac6d01821c65ebc2993edb87136d51eb670",
                "sha256:8b2952eb02aac23a82803bf3e25d94ea78f3d4674d972cc7324a712ad9d54b6f",
                "sha256:d76a5f910f6ba5bce12b14e396f8386d385d62bbc4c9d82af25ae956c11bb3aa",
                "sha256:8527ccd6bd857b844293f9efe34222229fa76e040d55dd03e019f305f7bd2a74",
                "sha256:4555572a6bb29d49eb9dbd1fb0938788ca7d772f441f8273626f1a12933fcee3",
                "sha256:0d9e9a9ce9e415229fa3c1953ec32c236bfde6a825f4a74a78013586071c02e8",
                "sha256:532b66f4569dfab5f87219c302ea23478e6ad9504863f2a7410c935593e6b526",
                "sha256:337ec6bae2225e56895f25ef88a874b2796e020332d63a35929f40e9e7fa158e",
                "sha256:73cb62467b8f9e06265bc00441cc3d8026d24ca3708d517a3df93ff5a787af77",
                "sha256:441e16cac4fe6b7abab2653886fbab030752e42c42bd508f1fa2f7f8c5df0fcf"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

# 删除镜像

使用docker rmi指令可以删除镜像。

# 查看现有镜像
[root@VM-8-5-centos ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 5107333e08a8        8 weeks ago         501MB
nginx               1.25.1              89da1fb6dcb9        6 months ago        187MB
# 删除镜像
[root@VM-8-5-centos ~]# docker rmi 5107333e08a8
Untagged: mysql:5.7
Untagged: mysql@sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Deleted: sha256:5107333e08a87b836d48ff7528b1e84b9c86781cc9f1748bbc1b8c42a870d933
Deleted: sha256:37fd5f1492d4e9cb540c52c26655f220568050438f804275e886200c8807ffb4
Deleted: sha256:1105a50d3483cb9f970e70cf5163e3352f0b2fe2ff07c6abcca6f34228e76dc5
Deleted: sha256:94187496c18bb11b78e71017f2774ad3c0a734da9749a46e917c4239504e9322
Deleted: sha256:ae59716eae3be604a4fd43e86fd2ad504cb06c89cc064c73c78eee651e675805
Deleted: sha256:97d26ca29ec287ff4bd09a49602c44cbcabcf3303ddc726b3b94cbe26dfe1c94
Deleted: sha256:27303974d12144264b32b8936ca7c90d72bdba939a9e791010201b3b1717c4c4
Deleted: sha256:4d4483f06dbe01282c10cb9e429a0be826c18c61048f7860dad49ae7f6bac927
Deleted: sha256:3b73a6f6b3298c568dcfb8fa5e96c581a1b5c0ad395b0c38f9addd0c79703124
Deleted: sha256:46446bf265a411a4a13a4adc86f60c9e0479a2e03273c98cafab7bc4151dd2bc
Deleted: sha256:1d5264146b09a27a8fc6801dc239a4962582ed27dd2fbd8ee708463a1857b06b
Deleted: sha256:cff044e186247f93aa52554c96d77143cc92f99b2b55914038d0941fddeb6623
# 查看现有镜像
[root@VM-8-5-centos ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.25.1              89da1fb6dcb9        6 months ago        187MB

# 创建镜像

有三种方式可以创建镜像:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建。

# 基于已有镜像的容器创建

实际实际Docker容器的过程中,我们往往会对容器本身的内容做一些调整,如果我们希望将调整后的容器制作为新的镜像,就可以使用docker commit指令来实现。

# 基于本地模板导入

可以直接从一个操作系统模板文件导入镜像(操作系统模板文件应该是Docker之前就有的东西)。Docker也是基于操作系统模板文件构建的,将模板文件下载到本地后,使用docker import 指令导入即可。

# 基于Dockerfile创建

docker的镜像分层如下,本地模板导入只会导入最下层的操作系统镜像。而Dockerfile则依赖操作系统镜像,在这个基础上,还可以创建其他的分层(个人理解)。

Dockerfile详细介绍

Dockerfile由一行行命令行语句组成,并且支持以#开头的注释行。
一般而言,Dockerfile分为四部分,分别是基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令。

# nginx的dockerfile

# 指定基础镜像信息,对应的操作信息是ubuntu
FROM ubuntu

# 指定维护者信息
MAINTAINER Victor Vieux <victor@docker.com>

# 镜像的操作指令
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server

# 容器启动时执行指令 这里的执行指令是启动Nginx
CMD /usr/sbin/nginx

提示

1.编写完成Dockerfile之后,可以通过docker build命令来创建镜像。
2.除了上面dockerfile中用到的FROM,MAINTAINER,RUN,CMD这4个核心指令之外,我们还可以使用EXPOSE,ENV,ADD,COPY,ENTRYPOINT,VOLUME,USER,WORKER,ONBUILD指令,这些指令的作用是为4个核心指令提供辅助支持。

# 上传镜像

可以使用docker push命令上传镜像到仓库,默认上传到DockerHub官方仓库(需要登录)。

# 存出和载入镜像

可以使用docker save和docker load命令来存出以及载入镜像(存出的docker镜像是一个tar包)。

# 存出镜像

docker save 0fdf2b4c26d3 > mysql.tar

# 载入镜像

docker load < mysql.tar

# 容器

# 创建容器

可以使用docker create指令创建容器,容器创建完成后,再使用docker start指令启动容器,也可以使用docker run指令创建并启动容器。

# 新建容器

使用docker create指令可以创建容器。

# 使用docker create指令创建容器
[root@VM-8-5-centos ~]# docker create mysql:5.7
113ad69face1a651ffa191d34cccd9174aaea71cda31a22c92f3fd5794abeb4f
# 直接使用docker ps,找不到容器
[root@VM-8-5-centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp   kieoo-service
# 需要增加-a参数,才能看到非运行状态的容器,可以看到mysql容器的状态是Created
[root@VM-8-5-centos ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
113ad69face1        mysql:5.7           "docker-entrypoint.s…"   11 seconds ago Created                                  nice_goodall
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp   kieoo-service

# 启动容器

使用docker start可以启动非运行状态的容器。

# 这里启动刚创建的mysql容器
[root@VM-8-5-centos ~]# docker start 113ad69face1
113ad69face1
# 并没有看到容器运行
[root@VM-8-5-centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp   kieoo-service
# 查看容器状态,发现状态是Exited,异常退出,说明start指令正常执行。
[root@VM-8-5-centos ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
113ad69face1        mysql:5.7           "docker-entrypoint.s…"   4 minutes ago       Exited (1) 12 seconds ago                        nice_goodall
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks                  0.0.0.0:80->80/tcp   kieoo-service

# 新建并启动容器

使用docker run指令可以同时完成容器创建以及启动。

# -p 参数 冒号前面是宿主机接口,冒号后面是容器接口
# -d 参数 以守护态运行
[root@VM-8-5-centos ~]# docker run -p 3306:3306 --name mysql-docker -e MYSQL_ROOT_PASSWORD=1111 -d mysql:5.7
e38ff7507a577551a2cc89ef8ed85b529af669fb5aac85d0f10bd8d6d22fd594
[root@VM-8-5-centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
e38ff7507a57        mysql:5.7           "docker-entrypoint.s…"   5 seconds ago       Up 4 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   mysql-docker
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp                  kieoo-service

# 守护态运行

可以在docker容器启动参数上增加-d参数,这样容器就会以守护态运行。

# 终止容器

使用docker stop指令可以终止容器的运行。

[root@VM-8-5-centos ~]# docker stop e38ff7507a57
e38ff7507a57
[root@VM-8-5-centos ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
e38ff7507a57        mysql:5.7           "docker-entrypoint.s…"   2 minutes ago       Exited (0) 22 seconds ago                        mysql-docker
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks                  0.0.0.0:80->80/tcp   kieoo-service

提示

使用docker restart指令可以先停止容器,再启动容器的运行。
使用docker logs指令可以查看容器的日志。

# 进入容器

在使用-d参数启动容器时,容器启动后会进入后台,用户无法看到容器中的信息。某些时候如果需要进入容器进行操作,可以使用docker exec指令。

[root@VM-8-5-centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp   kieoo-service
# -it指以交互状态运行
[root@VM-8-5-centos ~]# docker exec -it 3a100e2acfff /bin/bash
root@3a100e2acfff:/# ps aux

# 删除容器

使用docker rm可以删除容器,docker支持同时删除多个容器。

[root@VM-8-5-centos ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
1b3c2f4e7af6        mysql:5.7           "docker-entrypoint.s…"   2 seconds ago       Created                                          jolly_hugle
b6e40cb46b73        mysql:5.7           "docker-entrypoint.s…"   30 seconds ago      Exited (1) 29 seconds ago                        angry_faraday
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks                  0.0.0.0:80->80/tcp   kieoo-service
[root@VM-8-5-centos ~]# docker rm b6e40cb46b73 1b3c2f4e7af6
b6e40cb46b73
1b3c2f4e7af6
[root@VM-8-5-centos ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
3a100e2acfff        nginx:1.25.1        "/docker-entrypoint.…"   6 weeks ago         Up 6 weeks          0.0.0.0:80->80/tcp   kieoo-service

# 导入及导出容器

与镜像导出导入类似,容器也可以导出导入,对应导出指令为docker export,对应导入指令为docker import。

# 数据管理

在使用docker run命令的时候,使用-v标记可以在容器内创建一个数据卷,同时还可以将本地目录挂载到容器内作为数据卷。

# -p 参数 冒号前面是宿主机接口,冒号后面是容器接口
# -d 参数 以守护态运行
# -v 参数 多次挂载容器卷
[root@VM-8-5-centos ~]# docker run -d -p 80:80 --name kieoo-service -v /data/kieoo/front/docker_config/nginx/conf/default.conf:/etc/nginx/conf.d/default.conf -v /data/kieoo/front/dist:/usr/share/nginx/html -v /data/kieoo/front/docker_config/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /data/kieoo/front/docker_config/nginx/logs:/var/log/nginx nginx:1.25.1

# 网络基础配置

Docker目前提供了映射主机端口到宿主主机容器互联机制来为容器提供网络服务。

# 映射主机端口到宿主主机

使用-p参数可以完成容器内端口到宿主主机端口的映射。

# -p 参数 冒号前面是宿主机接口,冒号后面是容器接口
# -d 参数 以守护态运行
# -v 参数 多次挂载容器卷
[root@VM-8-5-centos ~]# docker run -d -p 80:80 --name kieoo-service -v /data/kieoo/front/docker_config/nginx/conf/default.conf:/etc/nginx/conf.d/default.conf -v /data/kieoo/front/dist:/usr/share/nginx/html -v /data/kieoo/front/docker_config/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /data/kieoo/front/docker_config/nginx/logs:/var/log/nginx nginx:1.25.1

# 容器互联机制

要实现网络互联机制,最好的方式是使用Docker Compse或者Kubernetes(不推荐使用--link的方式)。

# Docker的实现原理

就像进程依赖于操作系统实现一样(每一个进程都以为自己独占了CPU),Docker容器技术同样也依赖于操作系统实现(每一个容器都以为自己是一个独立的操作系统)。
Docker的实现主要依赖操作系统提供的命名空间(进程命名空间、网络命名空间、IPC命名空间、挂载命名空间、UTS命名空间。用户命名空间)、控制组(对内存资源进行限制,对CPU调度的优先级进行控制、对组进行隔离)、联合文件系统(支持为每一个成员目录设定只读、读写、写出权限)。