docker / docker-compose 使用说明[笔记]

Docker

image-20211010222257688

image-20211010222438820

一、概述

发布一个项目需要部署环境(Redis,ES, Hadoop……),在服务器上重新部署环境非常麻烦,不能够跨平台。

所以通过Docker用Windows全部处理完,最后再发布到Linux。

传统:开发jar,运维部署环境

现在:开发打包部署,一套流程完成

Docker为解决部署的问题提供了一套解决方案,构建镜像,部署时直接下载。

Docker通过一种隔离机制,将服务器空间运用到极致。

文档地址:https://docs.docker.com/get-started/

仓库地址:https://hub.docker.com/

docker能做什么

  • 更加快捷的交付和部署

    传统:一堆帮助文件,安装程序

    Docker:打包镜像发布测试,一键运行

  • 更快捷的升级和维护

    使用Docker后,可以将项目打包成镜像,服务器A,服务器B……

  • 更简单的系统运维

    容器化使环境都高度一致

  • 更高效的计算机资源利用

    Docker是内核级虚拟化,可以运行很多容器,服务器资源可以被充分利用

二、安装

2.1 docker的基本构成

镜像(Image):好比一个模版,可以通过这个模版创建容器,通过这个镜像可以创建多个容器,最终项目运行就是在容器中的

容器(Container):Docker通过容器技术,可以独立运行一个或一组。

​ 启动、停止、删除……基本命令

仓库( repository):分为私有和共有仓库,Docker Hub默认是国外的,可以配置国内镜像

2.2 安装

环境准备

  1. linux基础
  2. CentOS7
  3. XShell

环境查看

确定内核版本 3.10以上

[root@iZvjqtq16uz5ygZ /]# uname -r
3.10.0-957.21.3.el7.x86_64

确定系统版本为OS7

[root@iZvjqtq16uz5ygZ /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

安装

# 删除老版本docker
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 安装需要的包
sudo yum install -y yum-utils

# 设置docker镜像地址
# 阿里云版本
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 更新软件包索引
sudo yum makecache fast

# 安装docker
sudo yum install docker-ce docker-ce-cli containerd.io

# 启动docker
sudo systemctl start docker

# 查看安装成功
sudo docker version

# 测试
sudo docker run hello-world

# 查看镜像
sudo docker images

卸载

sudo yum remove docker-ce docker-ce-cli containerd.io
 
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

2.3 阿里云镜像加速

  1. 登陆阿里云找到容器服务

image-20210811174403223

  1. 找到镜像加速地址

image-20210811174508242

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://h3j2f7ww.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

2.3 回顾hello-world

执行顺序

image-20210811174916321

2.4 docker运行原理

docker是cs结构的,通过客户端请求守护进程

image-20210811175544746

docker为什么比vm快

  • docker比虚拟机有更少的抽象层
  • 它使用的是宿主机的内核,vm需要的是guest os

三、常用命令

3.1 帮助命令

docker version		   # 版本信息
docker info			   # docker容器信息,包括镜像和容器的数量
docker 命令 --help      #	帮助命令

3.2 镜像命令

docker images 查看镜像
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   5 months ago   13.3kB

# 解释
REPOSITORY	# 镜像仓库源
Tag			# 镜像标签
IMAGE ID	# 镜像ID
CREATED		# 镜像创建时间
SIZE		# 镜像大小
# 参数
-a	查看全部
-q	只显示id
-f	筛选
docker search 搜索镜像
[root@iZvjqtq16uz5ygZ ~]# docker search mysql
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11273     [OK]       
mariadb                           MariaDB Server is a high performing open sou…   4279      [OK]       
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   836                  [OK]
# 参数
-f	筛选
	--filter=STARS=3000	# 搜索3000收藏以上的

[root@iZvjqtq16uz5ygZ ~]# docker search mysql --filter=stars=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   11273     [OK]       
mariadb   MariaDB Server is a high performing open sou…   4279      [OK]       
docker pull 下载镜像
# 通过镜像名下载
[root@iZvjqtq16uz5ygZ ~]# docker pull mysql
Using default tag: latest	# 不指定版本默认下载最新
latest: Pulling from library/mysql
33847f680f63: Pull complete 	# 分层下载
5cb67864e624: Pull complete 
1a2b594783f5: Pull complete 
b30e406dd925: Pull complete 
48901e306e4c: Pull complete 
603d2b7147fd: Pull complete 
802aa684c1c4: Pull complete 
715d3c143a06: Pull complete 
6978e1b7a511: Pull complete 
f0d78b0ac1be: Pull complete 
35a94d251ed1: Pull complete 
36f75719b1a9: Pull complete 
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd	# 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest	# 真实地址

# 等价
docker pull mysql
docker pull docker.io/library/mysql:latest
# 通过镜像名并指定版本
[root@iZvjqtq16uz5ygZ ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
33847f680f63: Already exists # 已经存在的不会下载
5cb67864e624: Already exists 
1a2b594783f5: Already exists 
b30e406dd925: Already exists 
48901e306e4c: Already exists 
603d2b7147fd: Already exists 
802aa684c1c4: Already exists 
5b5a19178915: Pull complete 
f9ce7411c6e4: Pull complete 
f51f6977d9b2: Pull complete 
aeb6b16ce012: Pull complete 
Digest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
# 根据id或名称删除
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
mysql         5.7       8cf625070931   3 weeks ago    448MB
mysql         latest    c60d96bd2b77   3 weeks ago    514MB
hello-world   latest    d1165f221234   5 months ago   13.3kB
[root@iZvjqtq16uz5ygZ ~]# docker rmi -f 8cf625070931
Untagged: mysql:5.7
Untagged: mysql@sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Deleted: sha256:8cf6250709314f2fcd2669e8643f5d3bdebfe715bddb63990c8c96e5d261d6fc
Deleted: sha256:452fe6896278c26338d547f8d1092011d923785247c46629b374d3477fe28c84
Deleted: sha256:bd40bf60af5d06e6b93eaf5a648393d97f70998faa3bfa1b85af55b5a270cb35
Deleted: sha256:c43e9e7d1e833650e0ed54be969d6410efa4e7fa6e27a236a44a2b97e412ee93
Deleted: sha256:70f18560bbf492ddb2eadbc511c58c4d01e51e8f5af237e3dbb319632f16335b
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
mysql         latest    c60d96bd2b77   3 weeks ago    514MB
hello-world   latest    d1165f221234   5 months ago   13.3kB
# 删除所有镜像
[root@iZvjqtq16uz5ygZ ~]# docker rmi -f $(docker images -aq)
Untagged: mysql:latest
Untagged: mysql@sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd
Deleted: sha256:c60d96bd2b771a8e3cae776e02e55ae914a6641139d963defeb3c93388f61707
Deleted: sha256:5c8c91273faab368a6d659156f2569fa9f40b0e0139222fdf9eef073df4b3797
Deleted: sha256:33d8196a776f42a16f10395b66f10f91443b1fb194bca2a9b8dfb0deff5babb8
Deleted: sha256:3ec63323025213e3cabf17ac7933506dc5520ec49226a9764418f77ea60d35c8
Deleted: sha256:1f129b005b51b049ac84ed0775b82096d480b7d9308a9a137697f37346562266
Deleted: sha256:80ed209bd0434faa1ce31fbaab8508124dddf8f6502c5736ee4b8e46697a8477
Deleted: sha256:e53f0d35c77064014a5c1c1332d84d5f421a58418ca9c208bc470691c0e483e3
Deleted: sha256:75209fb28131d5537e73406ff0f6f508f3eb1f4d86c43d1d16df76fd28b9cc35
Deleted: sha256:34a01bee1a62a01034ffc3da48a3cb45716a0cf2e264c26663e02288e81c7ec2
Deleted: sha256:9f8bca37a56017fd3462d4fc329b0b20f97c2dd4c15e55a8e6ad1c023ab5552b
Deleted: sha256:c8a6e3f9a2412c28cd8c48e2c7bed5e7fbaa0ab6649add2dbe8641cb29b967f6
Deleted: sha256:0a26eacdbd862e75d064d817e8a5bcf5e060c2680c10f77ffa52757c0b8c3328
Deleted: sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4
Untagged: hello-world:latest
Untagged: hello-world@sha256:776b0895d5e2fcd5e80bcdd607adc45461ba11143ef3df531174bf00679f43fe
Deleted: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

3.3 容器命令

常用的命令

port  	  # 查看映射端口对应的容器内部源端口
pause	  # 暂停容器
ps        # 猎户容器列表
pull      # 从docker镜像源服务器拉取指定镜像或者库镜像
push      # 推送指定镜像或者库镜像至docker源服务器
restart   # 重启运行的容器
rm        # 移除一个或多个容器
rmi       # 移除一个或多个镜像 (无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除)
run       # 创建一个新的容器并运行一个命令
save      # 保存一个镜像为一个 tar 包【对应 load】
search    # 在 docker hub 中搜索镜像
start     # 启动容器
stop      # 停止容器
tag       # 给源中镜像打标签
top       # 查看容器中运行的进程信息
unpause   # 取消暂停容器
version   # 查看 docker版本号
wait      # 截取容器停止时的退出状态值

有了镜像才可以创建容器,我们先下载centos镜像来学习

[root@iZvjqtq16uz5ygZ ~]# docker pull centos
docker run 新建容器并启动
docker run [可选参数] image

# 参数
--name="Name"	容器字,用于区分容器
-d				后台运行
-it				使用交互方式运行,进入容器查看内容
-p				指定容器端口	-p 8080:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口(常用)
	-p 容器端口
	容器端口
-P				随机指定端口

# 测试,启动并进入容器
# 主机名就是镜像id
[root@iZvjqtq16uz5ygZ ~]# docker run -it centos /bin/bash
[root@a59a9d04ad2c /]#
[root@a59a9d04ad2c /]# ls		# 容器内的centos版本很多命令不完善
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@a59a9d04ad2c /]# exit		# 停止并退出
exit
[root@iZvjqtq16uz5ygZ ~]# 
docker ps 列出所有运行的容器
# docker ps 命令
		# 显示正在运行的容器
# 参数
-a		# 显示正在运行的+曾经运行的
-n=?	# 显示最近运行的
-q		# 只显示容器编号


[root@iZvjqtq16uz5ygZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZvjqtq16uz5ygZ ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                      PORTS     NAMES
a59a9d04ad2c   centos         "/bin/bash"   3 minutes ago   Exited (0) 48 seconds ago             inspiring_allen
61d006a19cdb   centos         "/bin/bash"   3 minutes ago   Exited (0) 3 minutes ago              awesome_elbakyan
8312aad0f6c6   d1165f221234   "/hello"      4 days ago      Exited (0) 4 days ago                 recursing_banzai

退出容器
# 停止并退出
exit
# 不停止退出
ctrl + P + Q
删除容器
# 删除指定容器(不能删除正在运行的容器,如果要删除加	-f)
docker rm 容器id

# 删除所有容器
docker rm $(docker ps -aq)
docker ps -a -q|xargs docker rm	
启动和停止容器
docker start 容器id	# 启动容器
docker stop 容器id	# 停止容器
docker restart 容器id	# 重启容器
docker kill 容器id	# 强制停止容器

3.4 常用其他命令

后台运行容器

# 命令:docker run -d 容器

# 问题docker ps 发现没有容器
# 常见的坑:docker容器使用后台运行,必须有一个前台进程,docker发现没有应用就会停止
# nigix:容器启动后发现自己没有提供服务,就是没有程序了

查看日志

# 命令:docker logs -t -f --tail 查看的条数 容器

# 参数
[root@iZvjqtq16uz5ygZ ~]# docker logs --help

Usage:  docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
  -n, --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)

查看容器中进程信息

# 命令:docker top 容器
[root@iZvjqtq16uz5ygZ ~]# docker top fd5dcdb7e3e9
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                21913               21893               0                   23:33               pts/0               00:00:00            /bin/bash

查看容器信息

# 命令:docker inspect 容器
[root@iZvjqtq16uz5ygZ ~]# docker inspect fd5dcdb7e3e9
[
    {
        "Id": "fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba""Created": "2021-08-18T15:33:45.889519607Z""Path": "/bin/bash""Args": []"State": {
            "Status": "running""Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 21913,
            "ExitCode": 0,
            "Error": """StartedAt": "2021-08-18T15:33:46.140591444Z""FinishedAt": "0001-01-01T00:00:00Z"
        }"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55""ResolvConfPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/resolv.conf""HostnamePath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/hostname""HostsPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/hosts""LogPath": "/var/lib/docker/containers/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba/fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba-json.log""Name": "/sharp_lichterman""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/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e-init/diff:/var/lib/docker/overlay2/3d0f44460bad8c9f659010f235579de50bb06b8cd48198e90098626252e85940/diff""MergedDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/merged""UpperDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/diff""WorkDir": "/var/lib/docker/overlay2/61f37a5a2acff47895e36f41643be6964ccf17288d24c807117fcce5364fcd6e/work"
            }"Name": "overlay2"
        }"Mounts": []"Config": {
            "Hostname": "fd5dcdb7e3e9""Domainname": """User": """AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ]"Cmd": [
                "/bin/bash"
            ]"Image": "centos""Volumes": null,
            "WorkingDir": """Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201204""org.label-schema.license": "GPLv2""org.label-schema.name": "CentOS Base Image""org.label-schema.schema-version": "1.0""org.label-schema.vendor": "CentOS"
            }
        }"NetworkSettings": {
            "Bridge": """SandboxID": "4f2e2f5c5d18962c52f9dc1aa9c158229ceba25218de723989ef07a00ce21182""HairpinMode": false,
            "LinkLocalIPv6Address": """LinkLocalIPv6PrefixLen": 0,
            "Ports": {}"SandboxKey": "/var/run/docker/netns/4f2e2f5c5d18""SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "b92b0c256a421f4c7f4f91fed818a4a1d99ea9602aba55763a15cfbfe94031d4""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": "d3816c025268349314dc2077d29c90f6bafeb26db39dfaff8803797ca61a0d9d""EndpointID": "b92b0c256a421f4c7f4f91fed818a4a1d99ea9602aba55763a15cfbfe94031d4""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
                }
            }
        }
    }
]

进入正在运行的容器

# 命令1:docker exec -it 容器 /bin/bash

# 命令2:docker attach 容器 /bin/bash

# 第一个是进入容器后开启新的终端,可以在里面操作
# 第二个是进入容器后打开当前正在运行的终端

拷贝文件

# 命令1:docker cp 容器:容器内路径 目的主机路径
# 该命令是把容器内的内容拷贝到外面

# 命令2:docker cp 目的主机路径 容器:容器内路径
# 该命令是把外面的内容拷贝到容器内(后面还有挂载)

四、任务

4.1 部署nginx

  1. 搜索镜像(不建议用search,建议去dockerhub去搜)

  2. 下载镜像

[root@iZvjqtq16uz5ygZ ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Pull complete 
e21006f71c6f: Pull complete 
f3341cc17e58: Pull complete 
2a53fa598ee2: Pull complete 
12455f71a9b5: Pull complete 
b86f2ba62d17: Pull complete 
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
  1. 查看镜像
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    dd34e67e3371   28 hours ago   133MB
centos       latest    300e315adb2f   8 months ago   209MB
  1. 启动容器
[root@iZvjqtq16uz5ygZ ~]# docker run -d --name nginx1 -p 3344:80 nginx
81e8a171d4bfbf9417e72b879fe8262b4bf010fa39139069a98be56f7039b931
  1. 测试
[root@iZvjqtq16uz5ygZ ~]# curl localhost:3306
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@iZvjqtq16uz5ygZ ~]# docker rm $(docker ps -aq)
Error response from daemon: You cannot remove a running container 81e8a171d4bfbf9417e72b879fe8262b4bf010fa39139069a98be56f7039b931. Stop the container before attempting removal or force remove
Error response from daemon: You cannot remove a running container fd5dcdb7e3e9897cbab2dad9724cbb6fb436187e53e316af4fe5ad6cd42a86ba. Stop the container before attempting removal or force remove
[root@iZvjqtq16uz5ygZ ~]# docker rm -f $(docker ps -aq)
81e8a171d4bf
fd5dcdb7e3e9
  1. 进入容器找到nginx配置文件
[root@iZvjqtq16uz5ygZ ~]# docker exec -it nginx1 /bin/bash
root@2b266e3c6ade:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@2b266e3c6ade:/# cd /etc/nginx/
root@2b266e3c6ade:/etc/nginx# ls
conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params

4.2 部署tomcat

官方使用

# docker run -it --rm tomcat:9.0

# 我们之前运行的容器关闭后都可以查到,加上  --rm  后容器关闭就会删除,一般用于测试

# 我们正常下载镜像之后再使用
[root@iZvjqtq16uz5ygZ ~]# docker pull tomcat

# 启动
[root@iZvjqtq16uz5ygZ ~]# docker run -d -p 3355:8080 --name tomcat1 tomcat
733463ab9a58c6193d80ddfe8422529e3e4ec3544ef87697bdedf948f9ec67e3

# 外网访问没有问题,但是404

# 我们进入容器查看发现webapps为空,我们把webapps.dist内所有内容复制到webapps中在查看,此时不会有404
root@733463ab9a58:/usr/local/tomcat/webapps.dist# cp -r webapps.dist/* webapps 
root@733463ab9a58:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

4.3 部署ES+Kibana

# es暴露的端口很多
# es十分占内存
# es的数据一般要放置在安全目录

# --net somenetwork  ? 网络配置
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

# 查看是否成功
{
  "name" : "b432915594c4""cluster_name" : "docker-cluster""cluster_uuid" : "VOvkXodJT7SwTGeCGdB0ng""version" : {
    "number" : "7.6.2""build_flavor" : "default""build_type" : "docker""build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f""build_date" : "2020-03-26T06:34:37.794943Z""build_snapshot" : false,
    "lucene_version" : "8.4.0""minimum_wire_compatibility_version" : "6.8.0""minimum_index_compatibility_version" : "6.0.0-beta1"
  }"tagline" : "You Know, for Search"
}

# 用docker stats查看cpu,可以看到,es占用了很大的内存
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O     
b432915594c4   elasticsearch   5.73%     1.249GiB / 1.694GiB   73.72%    1.18kB / 942B   314MB / 729kB  
PIDS
43
# 启动之后发现非常卡,甚至服务器都卡住了,es很消耗内存,那么如何解决呢?
# 我们先停止所有容器,对其进行内存限制

# 通过修改配置文件 -e 环境配置修改, 
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

五、docker镜像详解

5.1 镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含某个软件所需要的所有内容。

所有应用,直接打包docker镜像,就可以直接跑起来!

如何得到镜像?

  • 从仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像

5.2 docker镜像原理

UnionFS(联合文件系统)

我们下载的时候看到的一层层就是这个!

UnionFS(联合文件系统):是一种分层\轻量级并且高性能的文件系统,他支持文件系统的修改作为一次提交来一层层叠加,同时可以将不动目录挂载到同一个虚拟文件系统下,Union文件系统是docker镜像的基础。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件叠加起来,这样最终的文件系统就会包含所有底层的文件和目录

Docker镜像的加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

分层的镜像

以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载

img

为什么 Docker 镜像要采用这种分层结构呢

最大的一个好处就是 - 共享资源

比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

特点

Docker镜像都是只读的当容器启动时,一个新的可写层被加载到镜像的顶部。

这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

image-20210825170342182

5.3 提交镜像commit

docker commit 提交容器成为一个新的副本

docker commit -m="提交信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试

# 我们将官方tomcat中webapps.dist文件夹下的内容复制到webapps下(官方的不能直接运行)

# 然后exit退出镜像

# 提交我们自己的镜像
[root@iZvjqtq16uz5ygZ ~]# docker commit -m="add webapps" -a="JinWeimin" 733463ab9a58 mytomcat:1.0
sha256:d10f7bf3719ec5177044f850862d0983ca9fa550df3b3f6a0099e139ba084e40
# 此时我们自己的tomcat就已经在里面了
[root@iZvjqtq16uz5ygZ ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
mytomcat              1.0       d10f7bf3719e   25 seconds ago   673MB
nginx                 latest    dd34e67e3371   7 days ago       133MB
tomcat                latest    710ec5c56683   2 weeks ago      668MB
portainer/portainer   latest    580c0e4e98b0   5 months ago     79.1MB
centos                latest    300e315adb2f   8 months ago     209MB
elasticsearch         7.6.2     f29a1ee41030   17 months ago    791MB

六、容器数据卷

6.1 什么是容器数据卷

应用和环境运行在容器中,那么我们容器删除,数据就会丢失(数据库的数据等)

我们想要让这个数据可以持久化

此时需要一个容器见数据共享的技术,把数据保存在本地,Docker容器中产生的变化,同步到本地!

这就是卷技术!

目录的挂载,将我们容器内的目录,同步到本地。

总结:容器的持久化和同步操作!容器间的数据共享

6.2 使用数据卷

方式一:通过命令挂载

docker run -it -v 主机目录:容器内目录

# 测试
# 创建容器,进行挂载
# 使用 docker inspect 查看挂载情况 

image-20210825220321131

# 容器 --
[root@iZvjqtq16uz5ygZ usr]# docker run -it --name="myCentos" -v /home/test:/home centos
[root@a67776510c8c ~]# cd /home
[root@a67776510c8c home]# touch test.c

# 本地 --
[root@iZvjqtq16uz5ygZ home]# cd test
[root@iZvjqtq16uz5ygZ test]# ls
test.c
# 此时可以发现挂载后,容器被挂载的文件夹所有的改动都会同步在本地挂载的文件夹

好处:我们以后修改配置等,只需要在本地修改

6.3 实战:mysql的数据持久化

mysql的数据是放在data目录下的

# 安装mysql镜像
[root@iZvjqtq16uz5ygZ test]# docker pull mysql:8.0.21

# 创建容器 # 安装mysql主要要配置密码
官方:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# some-mysql 为容器名	tag为版本号		my-secret-pw为密码

# 在此基础上配置数据集挂载
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
-d \
-p 33060:3306 \
-v /home/docker/mysql/conf:/etc/mysql/conf.d \
-v /home/docker/mysql/data:/var/lib/mysql \
mysql:8.0.21

# 启动成功后,我们用workbench连接一下这个mysql数据库

image-20210825230513306

6.4 具名挂载和匿名挂载

# 匿名挂载
# docker run -P -d --name nginx1 -v /etc/nginx nginx

# 查看所有卷的情况
# docker volume ls
[root@iZvjqtq16uz5ygZ conf]# docker volume ls
DRIVER    VOLUME NAME
local     06e0151f0bd1ce53e9a3b105f3fa8e99fa0c068da523ab50028881420ff6ada4
local     637afa56c8ed6519a0b1e46b4ae564aed10042cd295cded5c7f5f8eff231033b
# 这种就是匿名挂载


# 具名挂载
# docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx nginx
# 查看卷的情况
[root@iZvjqtq16uz5ygZ conf]# docker volume ls
DRIVER    VOLUME NAME
local     jumingnginx
# 此时就是具名挂载


所有docker容器内的卷在没有指定目录时都是在 ‘/var/lib/docker/volumes/xxxxxx/_data’ 下

我们通过具名挂载可以方便的找到我们的卷

如何确定是匿名挂载还是具名挂载还是指定路径挂载?

-v 容器内路径			# 匿名挂载 
-v 卷名:容器内路径		   # 具名挂载
-v 容器外路径:容器内路径	 # 指定路径挂载

# 拓展
# 在容器内路径后加上ro/rw改变读写权限
docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx:ro nginx	# 只读
docker run -P -d --name nginx2 -v jumingnginx:/etc/nginx:rw nginx	# 可读写

# 只要有ro,就只能通过宿主机修改,无法通过容积修改

6.5 初识DockerFile

我们也可以通过DockerFile构建数据卷

DockerFile就是用来构建镜像的脚本

镜像是一层一层的,脚本一个个的命令,就是一层层镜像

我们先简单在 /home/docker-test 目录下编写一个简单的DockerFile文件

# /home/docker-test/dockerFile1
# 文件内容:  命令	参数

FROM centos

VOLUME ["volume1","volume2"]

CMD echo "----end----"

CMD /bin/bash

# 每一行命令就是镜像的一层

通过这个文件构建镜像

# -f	dockerFile的路径
# -t	镜像名称
[root@iZvjqtq16uz5ygZ docker-volume]# docker build -f ./dockerFile1 -t test/image .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volume1","volume2"]
 ---> Using cache
 ---> 334c4fdb5982
Step 3/4 : CMD echo "----end----"
 ---> Using cache
 ---> c09b17886130
Step 4/4 : CMD /bin/bash
 ---> Using cache
 ---> 671b3b46a050
Successfully built 671b3b46a050
Successfully tagged test/image:latest
[root@iZvjqtq16uz5ygZ docker-volume]# docker images
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
test/image      latest    671b3b46a050   11 minutes ago   209MB			# 这就是我们创建的镜像
mytomcat        1.0       d10f7bf3719e   2 days ago       673MB
nginx           latest    dd34e67e3371   10 days ago      133MB
tomcat          latest    710ec5c56683   2 weeks ago      668MB
centos          latest    300e315adb2f   8 months ago     209MB
mysql           8.0.21    8e85dd5c3255   10 months ago    544MB
elasticsearch   7.6.2     f29a1ee41030   17 months ago    791MB

我们通过这个镜像新建容器

[root@iZvjqtq16uz5ygZ docker-volume]# docker run -it 671b3b46a050 /bin/bash
[root@732c2589347e /]# ls -lah
total 64K
drwxr-xr-x   1 root root 4.0K Aug 27 15:41 .
drwxr-xr-x   1 root root 4.0K Aug 27 15:41 ..
-rwxr-xr-x   1 root root    0 Aug 27 15:41 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Aug 27 15:41 dev
drwxr-xr-x   1 root root 4.0K Aug 27 15:41 etc
drwxr-xr-x   2 root root 4.0K Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4.0K Dec  4  2020 lost+found
drwxr-xr-x   2 root root 4.0K Nov  3  2020 media
drwxr-xr-x   2 root root 4.0K Nov  3  2020 mnt
drwxr-xr-x   2 root root 4.0K Nov  3  2020 opt
dr-xr-xr-x 104 root root    0 Aug 27 15:41 proc
dr-xr-x---   2 root root 4.0K Dec  4  2020 root
drwxr-xr-x  11 root root 4.0K Dec  4  2020 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4.0K Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Aug 27 15:41 sys
drwxrwxrwt   7 root root 4.0K Dec  4  2020 tmp
drwxr-xr-x  12 root root 4.0K Dec  4  2020 usr
drwxr-xr-x  20 root root 4.0K Dec  4  2020 var
drwxr-xr-x   2 root root 4.0K Aug 27 15:41 volume1			# 这里发现volume1和volume2
drwxr-xr-x   2 root root 4.0K Aug 27 15:41 volume2			# 说明volume1和volume2已经被挂载了

由于我们在dockerFile中没有指定volume的名称,说明这是一个匿名挂载,挂载的文件夹也在默认目录下

这种创建数据卷的方式是我们常用的方式

6.6 数据卷容器

构建容器时 --volumes-from参数 可以让容器使用相同的容器数据卷

我们可能会想让多个容器的数据同步,比如mysql数据同步

image-20210827234741644

我们先创建一个我们自己镜像的容器

# docker01(数据卷容器)
[root@iZvjqtq16uz5ygZ docker-volume]# docker run -it --name docker01  671b3b46a050 /bin/bash
[root@745b1830cc3a /]# ls -lah
total 64K
drwxr-xr-x   1 root root 4.0K Aug 27 15:59 .
drwxr-xr-x   1 root root 4.0K Aug 27 15:59 ..
-rwxr-xr-x   1 root root    0 Aug 27 15:59 .dockerenv
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Aug 27 15:59 dev
drwxr-xr-x   1 root root 4.0K Aug 27 15:59 etc
drwxr-xr-x   2 root root 4.0K Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4.0K Dec  4  2020 lost+found
drwxr-xr-x   2 root root 4.0K Nov  3  2020 media
drwxr-xr-x   2 root root 4.0K Nov  3  2020 mnt
drwxr-xr-x   2 root root 4.0K Nov  3  2020 opt
dr-xr-xr-x 106 root root    0 Aug 27 15:59 proc
dr-xr-x---   2 root root 4.0K Dec  4  2020 root
drwxr-xr-x  11 root root 4.0K Dec  4  2020 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4.0K Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Aug 27 15:41 sys
drwxrwxrwt   7 root root 4.0K Dec  4  2020 tmp
drwxr-xr-x  12 root root 4.0K Dec  4  2020 usr
drwxr-xr-x  20 root root 4.0K Dec  4  2020 var
drwxr-xr-x   2 root root 4.0K Aug 27 15:59 volume1
drwxr-xr-x   2 root root 4.0K Aug 27 15:59 volume2

然后创建第二个和第三个容器,使用 --volumes-from 实现数据同步

docker run -it --name docker02 --volumes-from 745b1830cc3a 671b3b46a050 /bin/bash
docker run -it --name docker03 --volumes-from 745b1830cc3a 671b3b46a050 /bin/bash

我们通过 docker inspect发现,此时这三个容器挂载的目录是一样的,也就是说,他们共享一个数据卷

在三个容器任意一个中的被挂载的文件夹中修改数据,其他的都会产生相同的效果

实际上它们被挂载的部分使用的都是本机上的同一块地址,也就是volume默认的地址

此时删除任何一个容器,都不会影响到其他的容器

此时就做到了数据共享

多个mysql实现数据共享

# 第一个mysql容器
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql01 \
-d \
-p 33060:3306 \
-v /etc/mysql/conf.d \
-v /var/lib/mysql \
mysql

# 第二个mysql容器
docker run --name mysql1 \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql02 \
-d \
-p 33061:3306 \
--volumes-from mysql01 \
mysql

七、DockerFile

7.1 基础知识

dockerFile就是用来构建镜像的文件

构建步骤:

  1. 编写一个docker file
  2. docker build创建镜像
  3. docker push 发布镜像(docker hub/阿里云仓库)

7.2 docker file构建

基础知识:

  1. 每个关键字(指令)都是大写的
  2. 指令从上向下运行
  3. 每一个命令都是一层

7.3 docker file指令

指令作用
FROM基础镜像,镜像的构建基于这个基础镜像
MAINTAINER(deprecate)镜像是谁写的
LABEL添加原数据到镜像
RUN镜像构建时所需要执行的命令
ADD要添加的内容——比如要添加一个tomcat,就需要ADDcomcat的压缩包
WORKDIR镜像的工作目录
VOLUME挂载的目录
EXPOSE暴露的端口设置(随机映射)
CMD指定容器启动时需要执行的命令,只有最后一个会生效,可被替代
ENTRYPOINT指定容器启动时需要执行的命令,可以追加命令
ONBUILD当构建一个被继承docker file,这个时候ONBUILD会被执行
COPY类似ADD,将文件拷贝到镜像中
ENV构建时设置环境变量

7.4 实战测设

Docker中绝大多数的镜像都是FROM scratch

创建一个自己的centos

  1. 编写docker file
FROM centos

ENV MYPATH /usr/local

WORKDIR $MYPATH

LABEL "maintainer"="JinWeimin"

RUN yum install -y vim

RUN yum install -y net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "--end--"
CMD /bin/bash
  1. 通过build命令进行构建
# -f	dockerFile的路径
# -t	镜像名称
docker build -f ./my-centos-docker-file -t my-centos:1.0 .

我们可以通过 docker history查看镜像的构建历史

image-20211010211026460

创建tomcat

  1. 准备tomcat和jdk的压缩包

image-20211010212631993

  1. 编写Dockerfile文件,官方推荐Dockerfile为文件名,此时不需要指定-f

image-20211010213752823

  1. 通过docker build构建镜像

7.5 发布自己的镜像

Dockerhub

登陆自己的dockerhub账号

docker login -u 123456

推送镜像

# 先给镜像重新起个名
docker tag my-tomcat jin/my-tomcat:1.0
# 推送镜像
docker push jin/my-tomcat:1.0

阿里云

  1. 登陆阿里云

  2. 找到镜像仓库

  3. 创建命名空间

  4. 创建容器镜像

  5. 按照阿里云里面的命令推送

八、Docker网络

8.1 理解docker0

docker0就是个默认的网卡

docker每创建一个容器就会新创建一对网卡,容器通过与docker0桥接(bridge模式)来互相访问

linux系统再通过NAT(网络地址转换)访问到 eth0网卡进行与internet互联

8.2 自定义网络

查看所有的网络

image-20211011143602392

docker network ls

网络模式:

  • bridge: 桥接模式
  • none: 不配置网络
  • host: 与宿主机共享网络
  • container: 容器网络互联(用的少,局限很大)

测试:

# 我们新建容器时默认使用docker0
docker run -d -P --net bridge tomcat

创建

docker network create --subnet 192.168.0.0/16 --gateway 255.255.0.0 mynet

8.3 网络联通

不同网络正常是不能互相访问的的,所以我们要连接网络

# 这里的mynet是我们自定义的网络,tomcat是默认网络下的一个容器
docker network connect mynet tomcat
# 连接之后我们就可以让tomcat访问mynet里面的容器了

九、Springboot打包镜像

  1. 打包springboot项目
  2. 编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT [ "java" , "-jar" , " / app.jar"]
  1. 构建镜像

  2. 发布运行

IDEA插件 -> docker

Docker Compose

1. 初体验

  1. 创建一个文件夹
mkdir composedir
cd composedir
  1. 创建一个app.py文件
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
  1. 创建requirements.txt
flask
redis
  1. 创建Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
  1. 在一个Compose文件定义服务
version: "3.0"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
  1. 运行docker-compose
docker-compose up

docker-compose运行流程

  1. 创建网络
  2. 运行yml文件
  3. 启动service服务
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值