• Docker基础入门详解


    一、产生背景

    在传统软件开发流程中,研发程序员将功能代码研发完成后,交由测试人员进行测试,最后通过运维人员部署上线。但是在这个过程中,常常因为环境问题、配置问题、软件版本问题等等诸多因素,造成一些问题。Docker技术的出现就是为了解决因部署实施而带来的一系列问题。

    Docker技术实现了将开发环境、相关软件、配套环境等一系列研发环境打包成镜像文件,交由测试人员、运维人员使用。这样就减少了因部署而带来的一系列扯皮问题。除此之外,Docker提供了很多现成镜像,可以由用户直接使用,减少了一些中间件的安装。

    总之,Docker方便了软件的安装部署,实现了一个镜像,多处复用的效果。

    个人理解:
    在固定服务器,固定服务的场景下,不需要使用Docker技术。因为开发环境,测试环境,上线环境,都是固定不变的。不管是开发,测试还是运维,都是基于固定的环境和软件开展工作的。
    而对于一个服务,多处部署的应用场景,比较适合使用Docker技术。例如互联网大厂中,一个产品项目可能需要往全国甚至全世界多个机房中心中部署,那么这种场景就比较适合使用Docker技术。

    二、什么是Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。

    虚拟化容器:
    Docker采用虚拟化容器技术,虚拟化容器是在操作系统层面实现虚拟化,直接复用本地主机的操作系统,而虚拟化出容器所需的资源。虚拟化出来的容器是容器所具备功能所需的最小资源,没用的功能和组件,不会出现在容器中。所以Docker容器具有体积小的特性。这也是为何Docker容器中输入很多linux命令不识别的原因。因为没用的组件和功能,容器中默认是不携带的。

    虚拟化容器与虚拟机比较:
    传统虚拟机技术是在硬件层面实现的虚拟化技术,它将虚拟化出来一套完整的操作系统。而Docker容器是在本地主机操作系统基础上,虚拟化出来所需功能组件的最小容器。因此,传统虚拟机技术所产生的镜像比Docker容器的镜像更大,更笨重。

    三、Docker基本组成

    前提条件

    Docker要求运行在linux系统上,linux系统内核要求在3.8以上。在Centos系统上,要求centos7以上,64位操作系统。现在衍生出了Windows版本,其本质还是使用linux系统内核,只不过在Windows系统上模拟出了linux系统内核。

    Docker由镜像、容器和仓库组成:

    镜像

    这里的镜像,和传统虚拟机中的.iso镜像,有异曲同工之处。传统虚拟机中的.iso镜像文件放在虚拟机中,可以创建出操作系统实例来。在Docker中的镜像,可以创建出Docker容器实例。上面说过,Docker容器并不是整个操作系统,而是所需功能的最小容器。
    镜像就是一个模板,可以创建出很多容器实例。

    容器

    Docker镜像启动起来的每一个实例,都称之为容器。例如,redis镜像启动的容器,就是redis服务。mysql镜像启动的容器,就是mysql服务等。

    仓库

    存放镜像的地方,就是Docker的仓库。其机制类似于Maven仓库或git仓库。只不过存放的是Docker镜像。分为本地仓库和远程仓库。本地仓库就是宿主机本地存放镜像的地方。本地仓库没有的镜像,可以从远程仓库拉取。远程仓库分为公共远程仓库和私有远程仓库。公共远程仓库有Docker Hub或阿里云仓库。私有远程仓库就是公司 内部自己搭建的Docker仓库。私有远程仓库可安装Docker registry软件进行搭建。具体操作这里不再记录。Docker仓库运行流程如下:
    在这里插入图片描述
    我们自定义的镜像,也可以上传到远程仓库,供别人拉取使用。阿里云仓库是付费的。
    甜点: 在个人安装Docker的宿主机上,可配置阿里云提速器,来加快镜像的远程拉取速度。这里注意要区分与配置阿里云远程仓库地址。配置阿里云远程仓库地址可以用来加快拉取速度,因为Docker Hub是国外网站,拉取速度较慢。而这里 说的配置阿里云提速器,是在配置了阿里云仓库后,更进一步的提速效果。具体的配置方式是登陆自己的阿里云账号,然后搜索容器镜像服务,然后点击此选项,然后选择镜像提速器菜单,安装上面操作配置即可,如下图所示:
    在这里插入图片描述
    可以看出这是跟个人账号挂钩的一个操作,在个人学习时,可以配置使用。

    四、Docker基本操作命令大全

    系统级别命令

    在这里插入图片描述

    镜像相关命令

    1. 查看本地仓库镜像:
    docker images
    
    • 1

    输出字段及含义如下图:

    在这里插入图片描述
    其中一个镜像可以有多个TAG版本存在。使用某个版本,可以通过镜像名称:TAG来指定。当版本为latest时,可以省略:TAG。否则必须使用镜像名称:TAG

    1. 查询远程仓库镜像:
    docker search xxx
    
    • 1

    可以列出镜像,如下图所示:
    在这里插入图片描述
    其中OFFICAL代表是否官方。优先选择官方镜像进行拉取。这里只是搜索镜像,并不包含具体版本号,一般镜像包含了各个版本。我们可以直接在镜像名后面加我们想要的版本即可。如果不加版本,默认拉取latest版本。
    在Docker Hub官网,也可以搜索某个镜像。

    1. 拉取镜像到本地:
    docker pull 镜像名字[:TAG]
    
    • 1

    如果不加TAG,默认拉取最新的。

    1. 删除镜像:
    docker -rmi 镜像名字ID
    
    • 1

    镜像启动的所有实例必须停止运行才可以删除镜像。

    容器相关命令

    1. 启动容器命令:
    docker run
    
    • 1

    参数:

    --name xxx   #指定容器名称为xxx
    -d #后台运行,并返回容器ID,此方式开启容器后不进入容器
    -it #其实是-i和-t两个参数,一般都在一起使用,开启交互式容器,启动容器后进入容器内部
    -p 宿主机port:容器port  #指定宿主机端口与容器端口对应关系。可在宿主机上通过此端口访问容器服务
    -v 宿主机路径:容器内部路径  #将容器内部某个路径挂载到宿主机上,实现数据的同步和持久化
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 后台启动容器命令:
     docker run -d -p 1000:1000 --name 容器名称 镜像ID(镜像名称:TAG)
    
    • 1
    • 交互启动容器命令:
    docker run -it -p 1000:1000 --name 容器名称 镜像ID(镜像名称:TAG) /bin/bash
    
    • 1

    在交互式容器启动时,需要在命令后面加上/bin/bash或bash命令,这样才能进入容器内部,与容器内部进行交互。这点需要特别注意。

    退出容器:
    交互式进入容器后,如果退出容器到宿主机呢?两种方式:
    ctrl+D或exit命令退出容器,容器也会停止。
    ctrl+p+q退出容器,容器不会 停止。

    文件挂载:
    在容器中的数据,会随着容器的删除而删除,而且容器中配置文件的修改,需要先进入容器才能修改。使用文件挂载参数-v,将容器内文件与宿主机文件进行映射后,容器内文件和宿主机映射文件就会保持同步,在宿主机修改配置文件,容器内 对应配置文件也会修改(容器重启后生效)。在容器内产生的数据,在宿主机映射文件也会产生相应数据。
    例如在redis容器或mysql容器中,都需要将配置文件和数据文件进行挂载,一个是便于配置文件的修改,一个是对redis日志或mysql数据进行持久化保持。
    挂载命令:

    docker run -d --privileged=true -v 宿主机绝对路径:容器绝对路径 镜像名
    
    • 1

    其中--priviledge=true是授权参数,最好 加上,否则有时会出问题。
    2. 查看容器实例命令:
    查询正在运行的容器实例:

    docker ps
    
    • 1

    查看正在运行和已经停止的容器实例:

    docker ps -a
    
    • 1

    这里需要注意,当用某个镜像启动容器后,容器就会在宿主机存在。即使这个实例停止运行了,那么这个容器还是存在的,我们可以继续启动这个容器。

    • 启动某个容器命令:
    docker start 容器ID
    
    • 1

    关闭某个容器命令:

    docker stop 容器ID
    
    • 1

    删除容器命令:

    docker rm 容器ID
    
    • 1

    删除容器后,容器才会在宿主机消失。删除容器是rm,删除镜像是rmi,其中这个i就代表image镜像的意思。

    1. 进入某个容器命令
      上面讲到启动一个后台运行的容器,那么如果 想进入这个容器做交互,应该如何进去呢?执行以下命令:
    docker exec -it 容器ID  /bin/bash
    
    • 1

    退出按ctrl+D退出即可,因为是后台运行启动的,这样退出也不会停止容器运行。

    还有一个进入容器内部的命令:

    docker attach 容器ID
    
    • 1

    这种方式很少用,原因如下:
    在这里插入图片描述
    3. 查看容器详情命令:

    docker inspect 容器ID
    
    • 1

    返回json格式容器详情信息,内容很多,如下所示:

    [
        {
            "Id": "3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f",
            "Created": "2022-08-28T06:55:02.245198929Z",
            "Path": "docker-entrypoint.sh",
            "Args": [
                "redis-server"
            ],
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 21683,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2022-08-28T06:55:04.16474428Z",
                "FinishedAt": "0001-01-01T00:00:00Z"
            },
            "Image": "sha256:3edbb69f9a493835e66a0f0138bed01075d8f4c2697baedd29111d667e1992b4",
            "ResolvConfPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/resolv.conf",
            "HostnamePath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/hostname",
            "HostsPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/hosts",
            "LogPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f-json.log",
            "Name": "/keen_noether",
            "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,
                "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",
                "ConsoleSize": [
                    0,
                    0
                ],
                "Isolation": "",
                "CpuShares": 0,
                "Memory": 0,
                "NanoCpus": 0,
                "CgroupParent": "",
                "BlkioWeight": 0,
                "BlkioWeightDevice": [],
                "BlkioDeviceReadBps": null,
                "BlkioDeviceWriteBps": null,
                "BlkioDeviceReadIOps": null,
                "BlkioDeviceWriteIOps": null,
                "CpuPeriod": 0,
                "CpuQuota": 0,
                "CpuRealtimePeriod": 0,
                "CpuRealtimeRuntime": 0,
                "CpusetCpus": "",
                "CpusetMems": "",
                "Devices": [],
                "DeviceCgroupRules": null,
                "DeviceRequests": null,
                "KernelMemory": 0,
                "KernelMemoryTCP": 0,
                "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/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879-init/diff:/var/lib/docker/overlay2/8c626981a567a606070bdc8e00a103eed11d0859dcfce2763b37a4f2e257b668/diff:/var/lib/docker/overlay2/c19216a0ddf38928401b118816cda02bd497603ec3109647bd147eabef3c2dd8/diff:/var/lib/docker/overlay2/2d98fdbbe975db2295a238830f740242863eb62834e1c1288e9096f88aea17b6/diff:/var/lib/docker/overlay2/df05555cfad1eec6219f2cb14ec183be109d09f04a4a245dd755b619551492b8/diff:/var/lib/docker/overlay2/40df4c9e096704ba37d1e916faf0f02a012bd061b6883de5a3c12699b2f30e41/diff:/var/lib/docker/overlay2/f12fbd3a76a4f40e20699b214a894a19c32d6650b3824ed7fb7f47876531866d/diff",
                    "MergedDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/merged",
                    "UpperDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/diff",
                    "WorkDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/work"
                },
                "Name": "overlay2"
            },
            "Mounts": [
                {
                    "Type": "volume",
                    "Name": "9bd2c45c0f4711a8291c6eb4a2607aa20f9e23b402facef0be854925dfbba76f",
                    "Source": "/var/lib/docker/volumes/9bd2c45c0f4711a8291c6eb4a2607aa20f9e23b402facef0be854925dfbba76f/_data",
                    "Destination": "/data",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ],
            "Config": {
                "Hostname": "3d25328ac0bb",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "6379/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "GOSU_VERSION=1.14",
                    "REDIS_VERSION=7.0.4",
                    "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-7.0.4.tar.gz",
                    "REDIS_DOWNLOAD_SHA=f0e65fda74c44a3dd4fa9d512d4d4d833dd0939c934e946a5c622a630d057f2f"
                ],
                "Cmd": [
                    "redis-server"
                ],
                "Image": "redis",
                "Volumes": {
                    "/data": {}
                },
                "WorkingDir": "/data",
                "Entrypoint": [
                    "docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": {}
            },
            "NetworkSettings": {
                "Bridge": "",
                "SandboxID": "adfae3e2a0fae1e742453439bfe09024f92eb951b72eb4e363b965ff913c9c75",
                "HairpinMode": false,
                "LinkLocalIPv6Address": "",
                "LinkLocalIPv6PrefixLen": 0,
                "Ports": {
                    "6379/tcp": null
                },
                "SandboxKey": "/var/run/docker/netns/adfae3e2a0fa",
                "SecondaryIPAddresses": null,
                "SecondaryIPv6Addresses": null,
                "EndpointID": "2a3d532504abe9f43339fb9cd9e8021a726641819e7ce25e7c0ac4148a6bb925",
                "Gateway": "172.17.0.1",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "IPAddress": "172.17.0.2",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "MacAddress": "02:42:ac:11:00:02",
                "Networks": {
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "7667f6780a0f4b166b8487b3eca53cd6754fb92d16d599283ca3129f35c3a808",
                        "EndpointID": "2a3d532504abe9f43339fb9cd9e8021a726641819e7ce25e7c0ac4148a6bb925",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.2",
                        "IPPrefixLen": 16,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "02:42:ac:11:00:02",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224

    其中包含了容器的网络模式,ip,镜像,状态,挂载情况(Mounts)等等信息。总之容器的全部信息都可以在这里找到。
    4. 其他容器命令

    • 查看容器日志命令:
    docker  logs  容器ID
    
    • 1

    此命令在后台运行容器时使用,可以查看容器内服务运行日志。特别是容器运行失败或容器内服务出现问题时,可以通过该命令快速浏览容器软件所产生的日志。

    查看容器内部进程:

    docker top 容器ID
    
    • 1

    复制容器内文件到宿主机:

    docker cp 容器ID:容器内文件路径   宿主机存放文件路径
    
    • 1

    五、Dockerfile

    什么是Dockerfile

    上面我们讲到可以从远程仓库拉取现成的Docker镜像。那我们该如何制作自己的镜像呢?比如我们的项目打成jar包,在jdk里运行,想要把jdk环境和jar包制作成一个镜像,供其他人通过Docker进行运行,该如何做呢?这就用到了Dockerfile技术。

    Dockerfile是构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

    Dockerfile就是基于某个基础镜像,对镜像的一个增强脚本。比如,基于centos镜像,要安装jdk8环境,并且要运行我们项目的jar包。或者往centos镜像中添加ifconfig命令的功能,或者vim命令的功能。这都算是对基础镜像的一个增强。通过编写Dockerfile脚本文件,构建出一个新的镜像,包含上述的增强功能。

    构建Dockerfile三步曲

    • 编写Dockerfile文件
    • 使用Dockerfile文件构建镜像
    • 运行生成的镜像容器

    如下图所示:
    在这里插入图片描述

    Dockerfile语法指令

    上面提到Dockerfile是一个脚本文件,用来构建镜像增强。docker定义了Dockerfile的一些关键字指令(保留字指令)。这些指令特性如下:
    在这里插入图片描述
    下面看都有哪些指令:

    • FROM:
      指定加强镜像是基于哪个镜像做加强的。写在Dockerfile第一行。基于哪个镜像,用镜像名称:TAG表示即可。
    • MAINTAINER:
      Dockerfile作者和邮箱地址,可选项
    • RUN:
      用Dockerfile文件构建镜像时执行的命令,支持shell格式和exec格式两种。一般使用shell命令。在docker build构建镜像时执行RUN 后面定义的shell命令。
    • EXPOSE:
      容器服务对外暴露的端口。如tomcat镜像暴露8080端口,就是容器中tomcat暴露的端口。
    • WORKID:
      指定交互式进入容器后默认到达的目录,一个落脚点。
    • USER:
      指定镜像以什么用户来执行,如果不指定,默认是root用户。
    • ENV:
      用来构建镜像过程中设置环境变量。以k v形式定义。例如: ENV MYPATH /usr/local/tomcat表示设置MYPATH环境变量为/usr/local/tomcat。在Dockerfile中,就可以使用$MYPATH来代表这个路径。
    • VOLUME:
      容器数据卷,用于保存和持久化工作。等同于docker run -v 参数,在这里定义后无需在容器启动时指定了。
    • ADD:
      将宿主机文件拷贝到容器中,并解压。即宿主机中压缩文件拷贝到容器后,会自动解压出来。默认拷贝Dockerfile同级目录下的文件。所以要将Dockerfile文件和要拷贝进容器的文件放在同一个目录下。
    • COPY:
      类似于ADD命令,只不过没有自动解压功能。一般使用ADD命令。
    • CMD:
      定义在容器启动后,执行的命令。也是支持shell格式和exec格式。
      CMD [“可执行文件”,“参数1”,“参数2”…] 在容器启动后,执行shell命令,一般用于启动容器中的服务。例如tomcat容器中定义CMD命令,就是在tomcat容器启动后,执行CMD后面的命令,启动tomcat服务。
      Dockerfile文件中可以定义多个CMD命令,但只有最后一个生效。CMD会被docker run后面的参数替换。替换是当docker run后面的参数与CMD指令的作用相冲突时,以指令参数为准。当作用不冲突时,是叠加效果。

    需要注意的是,RUN指令后面的shell脚本是构建镜像时执行的命令,CMD指令是容器启动后执行的命令。

    • ENTRYPOINT:
      也是在容器启动时执行命令,类似于CMD。与CMD的区别是ENTRYPOINT不会被docker run后面的命令所覆盖(不理解这句话含义)。命令格式: ENTRYPOINT [“可执行文件”,“参数1”,“参数2”]。

    在这里插入图片描述
    ENTRYPOINT 作为启动容器的运行命令时,CMD命令就不再是运行命令了,而是ENTRYPOINT的一个参数。如上图例子,衍生出来的命令其实就是 nginx -c /etc/nginx/nginx.conf。其中nginx -c 是ENTRYPOINT命令,其是不会被用户后续追加命令覆盖的,后面的/etc/nginx/nginx.conf是CMD命令,其不再是运行命令,而是参数命令。而且它也保留CMD特性,会被后面的CMD命令所覆盖。如用户自定义了 -c /etc/nginx/new.conf后就将之前CMD命令覆盖了。

    tomcat Dockerfile文件查看

    在Docker Hub上搜索tomcat镜像,并选择第一个搜索结果(官方镜像),点进去后,选择自己想要查看的版本,如下图所示:
    在这里插入图片描述
    在这里插入图片描述
    这里看Dockerfile脚本文件的最后两行:
    在这里插入图片描述

    可以看到,tomcat容器暴露出来端口是8080,且容器启动后,执行catalina.sh命令。这就是启动tomcat服务的命令。所以启动tomcat镜像后,tomcat也就自动启动了。

    注意:
    当以交互式启动tomcat镜像时,不要加/bin/bash命令,因为这样会覆盖掉最后的CMD命令。这样就不会执行tomcat启动命令。这样容器 虽然启动了,但是tomcat没有运行。所以遇到这种情况时,就不要以交互式方式启动了,先以后台方式启动,然后再进入容器内部。

    Dockerfile构建镜像

    命令:

    docker build -t 新镜像名字:TAG
    
    • 1

    构建好的镜像自动进入docker本地镜像仓库,并不会生成具体某个可看见的文件。其中TAG版本号自己定义即可。定义好容器后启动容器即可。

    Docker执行Dockerfile的大致流程如下:

    1. docker从基础镜像运行一个容器
    2. 执行每一个指令对基础镜像进行修改
    3. 执行类似docker commit命令提交一个新的镜像层
    4. docker再基于新镜像运行一个新容器
    5. 执行Dockerfile下一条指令直至执行完毕。

    虚悬镜像

    在使用Dockerfile构建镜像时,有时会出现虚悬镜像。所谓虚悬镜像就是镜像名称和TAG都是none的镜像。虚悬镜像产生的原因可能是Dockerfile在一层一层的生成新的镜像时,所产生的垃圾镜像,没有用,直接删掉即可。

    六、网络模式

    查看网络模式命令:

    docker network ls
    
    • 1

    docker默认网络模式有如下三种:
    在这里插入图片描述
    在这里插入图片描述

    bridge桥接模式

    桥接模式是最常用的模式,也是默认模式。Docker服务会默认创建一个docker0网桥,如下图所示:
    在这里插入图片描述
    这样,每一个容器都会有自己的一个ip,ip网段和docker0的网段一样。这样就可以实现容器之间,容器与宿主机之间的通信。如下图所示:
    在这里插入图片描述
    其中,docker0是网桥,起到交换机的作用。网桥ip一般为172.17.0.1。容器ip为172.17.0.2等等。需要注意的是,容器每次重启后,ip都不是固定的,是随机变化的。

    Host模式

    想使用Host模式,在docker run命令后加参数–network host或-net host即可。使用host模式,容器ip和端口用宿主机ip和端口就行。Host模式容器详情中网络模式如下:
    在这里插入图片描述

    自定义网络模式

    docker支持自定义网络模式。我们除了上述几种网络模式外,我们可以自定义网络模式,命令如下:

    docker network create 网络名称
    
    • 1

    自定义创建的网络模式,本质还是用桥接模式。只不过网络名称是自己定义的。那么自定义网络模式有何作用呢?
    自定义网络模式是为了解决容器每次启动后,ip都会变化造成的问题。例如我们在连接数据库,redis时,配置文件写ip地址进行连接。当容器重启后,ip变了。那么数据库就连接不上了。
    容器使用自定义网络后,就可以通过容器名称进行容器的连接了。当连接mysql容器,redis容器的服务与mysql容器、redis容器都在同一个自定义网络时,就可以通过写容器 名称来代替ip地址,进行mysql和redis的连接。这样就规避了ip变化带来的问题。
    需要注意的是,所有的容器必须都在一个自定义网络中,且启动容器时必须通过 --name指定容器名称。如果不指定名称,docker自动生成的名称也不能通过容器名称访问。虽然自定义网络也是桥接模式,但是使用默认的桥接模式是不能通过容器名访问的。

    七、Dockerfile创建jar包镜像

    jdk8镜像制作

    首先,基于centos基础镜像制作jdk8镜像,编写Dockerfile文件:(Dockerfile文件和jdk8安装包需要在同一目录)

    vim Dockerfile
    
    • 1
    FROM centos:7
    
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    #安装vim编辑器
    RUN yum -y install vim
    #安装ifconfig命令
    RUN yum -y install net-tools
    #安装java8及lib库
    RUN yum -y install glibc.i686
    RUN mkdir /usr/local/java
    #ADD 是相对路径,jdk包和Dockerfile文件必须同一个目录下
    ADD jdk-8u281-linux-x64.tar.gz /usr/local/java
    #配置java环境变量
    ENV JAVA_HOME /usr/local/java/jdk1.8.0_281
    ENV JRE_HOME $JAVA_HOME/jre
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
    ENV PATH $JAVA_HOME/bin:$PATH
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "success"
    CMD /bin/bash
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    jar包镜像制作

    基于上述制作好的jdk8镜像,制作jar包镜像:(Dockerfile文件和jar包需在同一目录下)

    vim Dockerfile
    
    • 1
    FROM centosjava8:1.5
    MAINTAINER xiaoxiaosu
    #VOLUME指定临时文件目录为tmp,在主机/var/lib/docker目录下创建一个临时文件并连接到容器的tmp
    VOLUME /tmp
    ADD gulimall-product-0.0.1-SNAPSHOT.jar gulimall-product-0.0.1-SNAPSHOT.jar
    #运行jar包
    RUN bash -c 'touch gulimall-product-0.0.1-SNAPSHOT.jar'
    ENTRYPOINT ["java","-jar","gulimall-product-0.0.1-SNAPSHOT.jar"]
    EXPOSE 10001
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    八、Docker-Compose技术

    简介

    Docker-Compose是Docker官方开源项目,负责对Docker容器集群的快速编排。需要编写一个docker-compose.yml文件,在里面通过命令管理多个Docker容器,管理多个容器之间的协调,来共同服务于一项项目。通过docker-compose.yml进行多个容器的一键启停操作。
    在这里插入图片描述
    docker-compose需要单独安装。可参考文章:docker-compose教程(安装,使用, 快速入门)

    使用步骤

    1.编写Dockerfile并构建各个微服务镜像
    2.使用docker-compose.yml定义一个完整的业务单元,安排好整体应用程序中各个容器服务
    3.执行docker-compose up命令,一键启动项目

    compose相关命令

    在这里插入图片描述

    docker-compose.yml文件编写

    详细配置可参考文章:docker-compose.yml的详细解释与说明
    下面是一个自己练习的demo:

    version: "3"
    services:
        microService: #实例名称,随便定义,不重复就行
          image: gulimall_product
          container_name: ms01 #容器名称,不写这个参数默认就是microService
          ports:
              - "10001:10001"
          volumes:
              - /app/microService:/data
          networks:
              - ceshi
          depends_on:
              - redis
    
        #以上命令相当于写了一个docker run命令:docker run -d -p 10001:10001 -v /app/micorService:/data --network ceshi --name ms01 gulimall_product:latest
        redis:
          image: redis
          ports:
              - "6379:6379"
          volumes:
              - /app/redis/redis.conf:/etc/redis/redis.conf
              - /app/redis/data:/data
          networks:
              - ceshi
          command: redis-server /etc/redis/redis.conf
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    写完yml文件后,通常执行下面命令检查编写的yml文件是否有问题:

    docker-compose config -p
    
    • 1

    如果没有任何输出,代表编写yml文件没问题。在docker-compose.yml中都规定同一个自定义网络模式,在就可以使用服务名进行通信了,如mysql连接,redis连接等,都可以使用docker容器实例名配置。

    一键部署,一键启停,十几个二十几个docker实例用docker-compose编排就可以。再多了就考虑引入K8s。中小型公司用docker-compose足够了。

    九、监控统计

    轻量级使用Portainer监控工具进行监控。docker用命令能完成的工作,都可以使用Potainer工具进行图形操作,例如拉取镜像,启动容器,查看容器详情,查看网络等等,总之一切可以用命令完成的操作,都可以用Portainer图形操作完成。

    重量级的健康使用CAdvisor+InfluxDB+grafana进行监控。但是需要用到重量级监测的体谅的项目,直接使用K8s了,所以很少使用Docker的这个监控。

  • 相关阅读:
    二进制十六机制CRC总和异或等工具类
    golang[ssa & callgraph] 获取调用图实战
    【煤矿虚拟仿真体验】VR采煤机技能培训有效提高训练效果
    详解设计模式:迭代器模式
    第五章 Java编程-异常处理
    “我转行做测试开发的这一年多,月薪5K变成了24K”
    FunnyBirds: 一个用于解释人工智能方法的基于部分的分析的合成视觉数据集
    DevEco Studio 3.1差异化构建打包,提升多版本应用开发效率
    通用深度模型UniverSeg:分割医疗图像
    蓝桥杯每日一题2023.11.14
  • 原文地址:https://blog.csdn.net/qq1309664161/article/details/126694531