文章目录
- 一、概述
- 二、安装Docker
- 三、Docker常用命令
- 1. 查看信息
- 2. 镜像命令
- 3. 容器命令
- 1. docker run(新建容器并启动)
- 2. docker ps(列出容器)
- 3. exit/Ctrl + P + Q(退出容器)
- 4. docker rm(删除容器)
- 5. docker start/stop(启动和停止容器)
- 6.docker exec(进入当前正在运行的容器(打开新终端))
- 7. docker attach(进入当前正在运行的容器(进入容器启动命令的终端,不会启动新的线程))
- 8. docker cp(在容器和本地文件系统之间复制文件/文件夹)
- 9. docker top(查看容器中进程信息)
- 10. docker logs(日志信息)
- 11. docker inspect(返回容器详细信息)
- 12. docker stats(监控容器资源消耗)
- 四、数据卷
- 五、网络
- 六、DockerFile
- 七、Docker Compose
- 1. 简介
- 2. 安装
- 3. 快速开始
- 4. yaml配置文件
- version:版本
- services:多个容器集合
- build:指定Dockerfile
- command:覆盖容器启动后默认执行的命令
- container_name:自定义生成的容器名称
- depends_on:设置依赖关系
- dns:配置 dns 服务器
- dns_search:配置 DNS 搜索域
- env_file:从文件中获取环境变量
- environment:环境变量配置
- entrypoint:启动容器后执行的命令
- expose:暴露端口
- extra_hosts:添加主机名映射
- image:指定服务所使用的镜像
- links:链接到另一个服务中的容器
- logging:服务的日志记录配置
- network_mode:设置网络模式
- networks:配置容器连接的网络
- ports:对外暴露的端口定义,和 expose 对应
- volumes:卷挂载路径
- restart: always:设置容器自启动
- 5. 常用命令
- 八、可视化
- 九、示例
一、概述
-
Docker官方网址:https://www.docker.com/
-
Docker文档地址:https://docs.docker.com/get-docker/,Docker 的文档是超级详细的。
-
Docker仓库地址:https://hub.docker.com/,类似于github,可以把镜像发布到仓库上,也可以让别人获取
1. 什么是Docker
docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源。
docker可以让开发者打包他们的 应用 以及 依赖包 到一个轻量级、可移植的容器中,然后发布到任何流行的linux服务器,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类iphone的app),并且容器开销极其低。
2. 容器化技术与虚拟机技术的区别
-
虚拟机(virtual machine)就是带环境安装的一种解决方案 。
它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:资源占用多、冗余步骤多、启动慢。 -
由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为LXC)。
Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
比较了容器技术和虚拟机技术的不同之处:
-
传统虚拟机技术,虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。
-
而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
-
每个容器之间互相隔离,每个容器有自己的文件系统,容器之间进程不会相互影响,能区分计算资源。
3. Docker的优势
官方的话:
- 灵活:即使是最复杂的应用也可以集装箱化。
- 轻量级:容器利用并共享主机内核。
- 可互换:您可以即时部署更新和升级。
- 便携式:您可以在本地构建,部署到云,并在任何地方运行。
- 可扩展:您可以增加并自动分发容器副本。
- 可堆叠:您可以垂直和即时堆叠服务。
4. Docker的架构
-
Client
(客户端):通过一些命令与Docker
服务器作交互,比如说docker build
:构建一个容器;docker pull
:接取一个容器;docker run
:运行一个容器 -
Docker_host
(服务器):Docker 的操作都在这里执行-
Docker daemon
(守护进程):Docker
架构中的主体部分- 提供
Server
的功能使其可以接受Docker Client
的请求 - 当需要容器镜像时,则从
Registry
中下载镜像
- 提供
-
Images
(镜像):docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。 -
Containers
(容器):Docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。(初学者可以暂时把这个容器理解为就是一个简易的linux)可以把镜像理解成是 java 中的类,而容器理解成 java 中的对象实例,一个类可以拥有多个对象实例
-
-
Register
(远程仓库):存放镜像的地方,分为公有仓库和私有仓库
二、安装Docker
这部分可以参照官方文档:https://docs.docker.com/get-docker/,根据自己的系统去进行安装,我这里使用的系统是 Centos 7
在 Centos 系统上安装 Docker,这部分在官方文档的位置(其它Linux发行版安装方法也在这):https://docs.docker.com/engine/install/centos/
1. 服务器有网络时
-
卸载旧版本
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
-
需要的安装包
yum install -y yum-utils
-
设置存储库
# 官方给的代码,存储库是国外的,下载慢 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 推荐使用阿里云的镜像仓库 yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
-
安装 Docker 引擎
docker-ce:ce表示社区版,还有个ee,表示企业版# 安装前可以先更新软件包索引(非必须) yum makecache fast # 安装最新版的 Docker 引擎,包括docker社区版,docker社区版客户端等 yum install docker-ce docker-ce-cli containerd.io
-
启动 Docker
systemctl start docker
-
测试是否成功安装 Docker
# 查看 Docker 的版本号 docker version
出现下图则说明安装成功:
-
测试下载 hello-world 镜像
docker run hello-world
-
查看下载的 hello-world 镜像
docker images
-
卸载 Docker
# 卸载Docker Engine,CLI等 yum remove docker-ce docker-ce-cli containerd.io # 主机上的镜像,容器,等文件不会自动删除,需要手动删除 # /var/lib/docker docker的默认工作路径 rm -rf /var/lib/docker
2. 配置阿里云镜像加速
- 登录阿里云(https://www.aliyun.com/),找到容器镜像服务:
- 如果没有开通的话,就跟着阿里云的步骤开通一下。
- 找到最下面的镜像加速器,选择自己对应的系统,跟着步骤一步一步走就 ok 了
3. 服务器无网络时
这部分可以参照官方文档:从二进制文件安装Docker Engine
下面安装过程是在rhel7.3系统上进行的
-
安装依赖包:
yum install -y yum-utils device-mapper-persistent-data lvm2
-
查看自己服务器的架构:
uname -a
我的是x86 64位的:
-
然后要下载好
docker
的二进制安装文件压缩包,地址:https://download.docker.com/linux/static/stable/根据第二步查出的架构,选择相应架构下的压缩包,版本自己选择,我这里下载的是:
x86_64/docker-19.03.9.tgz
-
拷贝压缩包到机器中并解压:
tar xzvf docker-19.03.9.tgz
-
将解压好的文件拷贝到
/usr/bin/
目录下:cp docker/* /usr/bin/
-
启动Docker守护程序:
dockerd &
-
测试docker是否安装成功:
docker version
如下则说明安装成功:
4. 配置文件 daemon.json
docker安装后默认没有 daemon.json
这个配置文件,需要进行手动创建。配置文件的默认路径:/etc/docker/daemon.json
官方的配置地址: https://docs.docker.com/engine/reference/commandline/dockerd/#options
这个博客对一些配置进行了解释:docker配置文件docker-daemon.json详解
我用到的一些配置:
{
"registry-mirrors": ["http://harbor.test.com"], #镜像加速地址
# 这样配置,容器的日志文件会放到 /var/log/containers 目录下,就可以用EFK搜索出来对应的信息了
"exec-opts": ["native.cgroupdriver=systemd"], # Centos中默认是有两个,这里统一使用systemd
"log-driver": "json-file", # 存储日志的类型
"log-opts": {
"max-size": "100m" # 限制日志的大小
},
"insecure-registries": ["https://hub.zyx.com"] # 配置私有仓库地址
}
修改完后,需要下面两个步骤使新的配置生效
# reload配置文件
systemctl daemon-reload
# 重启docker
systemctl restart docker
三、Docker常用命令
官方文档:Docker的所有命令:https://docs.docker.com/reference/
1. 查看信息
1. docker --help(帮助信息)
命令 | 说明 |
---|---|
docker --help | 查看全部命令 |
docker 命令 --help | 查看某个命令的帮助信息 |
2. docker info(详细信息)
命令 | 说明 |
---|---|
docker info | 显示docker的系统信息,包括镜像和容器的数量 |
3. docker version(版本信息)
命令 | 说明 |
---|---|
docker version | 打印docker版本信息 |
2. 镜像命令
1. docker images(查看镜像)
-
命令:
docker images [OPTIONS] [REPOSITORY[:TAG]]
-
常用可选项:
名称,速记 默认 描述 --all
,-a
列出所有镜像(默认隐藏中间镜像) --quiet
,-q
只显示镜像的ID -
例子:
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest bf756fb1ae65 5 months ago 13.3kB
- 解释
REPOSITORY
:镜像的仓库源(名字)TAG
:镜像的标签(版本)IMAGE ID
:镜像的 idCREATED
:镜像的创建时间SIZE
:镜像的大小
- 解释
2. docker search(在仓库中搜索镜像)
-
命令:
docker search [OPTIONS] TERM
-
常用可选项:
名称,速记 默认 描述 --filter
,-f
根据提供的条件过滤输出,格式为 key=value
对。
如果有多个过滤器,则传递多个标志
(例如--filter is-automated=true --filter stars=3
) -
例子:
docker search --filter stars=3 busybox NAME DESCRIPTION STARS OFFICIAL AUTOMATED busybox Busybox base image. 325 [OK]
3. docker pull(下载镜像)
-
命令:
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
如果不写tag
(版本),默认就是latest
-
例子:
# 拉取最新版,下面的命令相当于: docker pull mysql:latest docker pull mysql # 拉取指定版本,需要确定在仓库中存在该版本 docker pull mysql:5.7
4. docker rmi(删除镜像)
-
命令:
docker rmi [OPTIONS] IMAGE [IMAGE...]
可以删除一个或多个镜像,可以通过镜像的名字或者 id 删除 -
常用可选项:
名称,速记 默认 描述 --force
,-f
强制删除图像 -
例子:
# 删除指定镜像 docker rmi -f e73346bdf465 # 删除所有的镜像 docker rmi -f $(docker images -aq)
5. docker commit(通过容器生成镜像)
-
命令:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
-
常用可选项:
名称,速记 默认 描述 -m
指定提交的说明信息 -a
提交的镜像作者 -c
使用 Dockerfile 指令来创建镜像 -p
在 commit 时,将容器暂停 -
例子:
# 对一个tomcat容器进行了修改后(webapps文件中添加了app),其中7e119b82cff6表示一个容器 docker commit -a "xiaoMaNong" -m "add webapps app" 7e119b82cff6 tomcat:v01 # 然后查看本地的镜像,可以发现看到刚提交的镜像 docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat v01 37af1236adef 15 seconds ago 652 MB
6. docker save/load(镜像的打包与加载)
-
docker save
:将一个或多个镜像保存到tar
存档(默认情况下流式传输到STDOUT)-
命令:
docker save [OPTIONS] IMAGE [IMAGE...]
-
常用可选项:
名称,速记 默认 描述 --output
,-o
写入文件,而不是STDOUT -
-
docker load
:从tar
存档或STDIN
加载图像-
命令:
docker load [OPTIONS]
-
常用可选项:
名称,速记 默认 描述 --input
,-i
从 tar 存档文件而非 STDIN 中读取 -
-
例子:
# 将镜像保存到本地 tar 文件 docker save -o mysql5.7 mysql:5.7 # 另一台服务器上无外网,将上面保存的 tar 包发送到该服务器,然后加载 sudo docker load -i mysql5.7
3. 容器命令
说明:有了镜像才可以创建容器
1. docker run(新建容器并启动)
-
命令:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
-
常用可选项:
名称,速记 默认 描述 --name="Name"
为容器分配一个名称,名称是唯一的,可以用名称来确定容器 --detach
,-d
后台方式运行 -it
使用交互方式运行,进入容器查看内容 --rm
退出时自动删除容器 --publish
,-p
将容器的端口发布到主机,使用方法: -p ip:主机端口:容器端口
-p 主机端口:容器端口
(常用)-p 容器端口
容器端口
--publish-all
,-P
将容器的端口随机分配到主机的空闲端口上,可以使用 docker ps -a
查看--volume
,-v
绑定挂载目录,使用方法: -v /本地目录:容器目录
匿名挂载:-v 容器目录
具名挂载:-v 卷的名字:容器目录
(详见 四、容器数据卷)--net
bridge 将容器连接到一个网络中,不指定会以桥接的方式连接到 docker0 –restart=always 设置容器自启动,docker 服务重启后容器也跟着重启 -
例子:
设置容器自启动
在运行 docker
容器时可以加如下参数来保证每次 docker
服务重启后容器也自动重启:
docker run --restart=always
如果容器已经启动了则可以使用如下命令:
docker update --restart=always <CONTAINER ID>
后台启动容器的坑
当以后台运行的方式启动了一个容器后,再使用 docker ps
命令发现,容器并没有在运行
[root@localhost ~]# docker run --name="centos_test" -d centos
1f38528aade344433c9d9c0b35125e3ea8007380e599c7b4a875944599481d30
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 原因:docker 容器使用后台运行,就必须要有一个前台进程,如果 docker 发现没有应用,就会自动停止。
- 解决方法:
docker run -dit centos /bin/bash
- 添加
-it
参数交互运行 - 添加
-d
参数后台运行 - 这样就能启动一个一直停留在后台运行的Centos了
- 注意:进入容器的方法要使用
exec
,不要使用attach
命令,attach
命令就是使用现有终端,如果你要退出容器操作,那么bash
结束,容器也就退出了
- 添加
2. docker ps(列出容器)
-
命令:
docker ps [OPTIONS]
不加任何参数默认显示为正在运行的容器 -
常用可选项:
名称,速记 默认 描述 --all
,-a
显示所有容器 --last
,-n=?
-1 显示n个最后创建的容器(包括所有状态) --quiet
,-q
仅显示数字ID -
例子:
[root@localhost /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6097bc8e3852 centos "/bin/bash" 10 minutes ago Exited (0) 9 minutes ago sad_lamport ea55e44464ae bf756fb1ae65 "/hello" 3 hours ago Exited (0) 3 hours ago unruffled_chandrasekhar
- 解释:
CONTAINER ID
:容器idIMAGE
:镜像COMMAND
:引用命令CREATED
:创建容器的时间STATUS
:容器状态PORTS
:暴露的端口NAMES
:容器名称
- 解释:
3. exit/Ctrl + P + Q(退出容器)
docker run -it name
进入容器之后,使用如下的命令退出容器
exit
:容器停止并退出
Ctrl + P + Q
:容器不停止退出
4. docker rm(删除容器)
-
命令:
docker rm [OPTIONS] CONTAINER [CONTAINER...]
命令中的 CONTAINER 用容器的 id/name -
常用可选项:
名称,速记 默认 描述 --force
,-f
强制删除正在运行的容器(使用SIGKILL) -
例子:
# 删除所有的容器 docker rm -f $(docker ps -aq) docker ps -aq | xargs docker rm -f
5. docker start/stop(启动和停止容器)
docker start 容器id/name # 启动容器
docker restart 容器id/name # 重启容器
docker stop 容器id/name # 停止当前运行的容器
docker kill 容器id/name # 强制停止运行的容器
6.docker exec(进入当前正在运行的容器(打开新终端))
-
命令:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
-
常用可选项:
名称,速记 默认 描述 -it
以交互模式运行 -
例子:
docker exec -it centos1 /bin/bash
7. docker attach(进入当前正在运行的容器(进入容器启动命令的终端,不会启动新的线程))
- 命令:
docker attach [OPTIONS] CONTAINER
8. docker cp(在容器和本地文件系统之间复制文件/文件夹)
-
命令:
# 在本地系统执行 # 将容器中的文件拷贝到本地文件系统中 docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH # 将本地系统文件拷贝到容器中 docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
9. docker top(查看容器中进程信息)
# 类似于 linux 中的 top 命令
docker top CONTAINER
10. docker logs(日志信息)
-
命令:
docker logs [OPTIONS] CONTAINER
-
常用可选项:
名称,速记 默认 描述 --follow
,-f
跟踪日志输出 --tail
all 从日志末尾开始显示的行数 --timestamps
,-t
显示时间戳 -
例子:
# 显示全部日志
docker logs -ft centos_test
# 显示10条日志
docker logs -ft --tail 10 centos_test
11. docker inspect(返回容器详细信息)
docker inspect CONTAINER
例子(标注了常用的信息):
[root@localhost ~]# docker inspect c2b030acf83a
[
{
"Id": "c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6",//容器id,一般使用的是前12位
"Created": "2020-06-07T15:04:33.788916436Z",//容器创建时间
"Path": "/bin/bash", //默认控制台
"Args": [], //传递的参数
"State": { //容器的状态
"Status": "running", //running 表示正在运行
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 101264, //进程id
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-06-07T15:04:35.115091831Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",//镜像的id
"ResolvConfPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/hostname",
"HostsPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/hosts",
"LogPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6-json.log",
"Name": "/zyx",
"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,
"Capabilities": null,
"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/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90-init/diff:/var/lib/docker/overlay2/02399b4c6980e3092721d60619f83c651885c0b0eb1241a6417f0bddb44b5463/diff",
"MergedDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/merged",
"UpperDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/diff",
"WorkDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/work"
},
"Name": "overlay2"
},
"Mounts": [], //数据卷挂载
"Config": { //基本配置
"Hostname": "c2b030acf83a", //容器名字
"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": [
"/bin/bash"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20200114",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS",
"org.opencontainers.image.created": "2020-01-14 00:00:00-08:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
}
},
"NetworkSettings": { //网络的一些设置
"Bridge": "",
"SandboxID": "70097fb845389da1a20faf75eabb2f84866ba4b38ea8388397a840b9a344aa85",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/70097fb84538",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "cb235799991b3c585bf97ea5fcdfc7a069aa13554a5f84ea35e6172c9cad2ed5",
"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": "020a4fab0d00a01941b764d9f16740807b2c2673b8138d7e1ece968086b5475b",
"EndpointID": "cb235799991b3c585bf97ea5fcdfc7a069aa13554a5f84ea35e6172c9cad2ed5",
"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
}
}
}
}
]
12. docker stats(监控容器资源消耗)
- 命令:
docker stats [OPTIONS] [CONTAINER...]
- 常用可选项:
名称,速记 默认 描述 --all
,-a
默认仅显示运行中的容器 显示所有容器 --format string
格式化输出 --no-stream
只返回当前的状态
例子:
# 查看当前运行中的所有容器资源
> docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
fdedc094cd26 dockercompose_nginx_1 0.00% 2.148MiB / 3.696GiB 0.06% 4.86MB / 4.78MB 0B / 0B 3
68189b6d290f dockercompose_kibana_1 0.00% 413.7MiB / 3.696GiB 10.93% 125MB / 96.4MB 263MB / 113MB 22
22ed88ee3afa dockercompose_elasticsearch_1 0.39% 524.9MiB / 3.696GiB 13.87% 133MB / 252MB 72.4MB / 2.85MB 62
# 格式化为 json
> docker stats --no-stream --format "{\"container\":\"{{ .Container }}\",\"memory\":{\"raw\":\"{{ .MemUsage }}\",\"percent\":\"{{ .MemPerc }}\"},\"cpu\":\"{{ .CPUPerc }}\"}"
{"container":"fdedc094cd26","memory":{"raw":"2.148MiB / 3.696GiB","percent":"0.06%"},"cpu":"0.00%"}
{"container":"68189b6d290f","memory":{"raw":"413.8MiB / 3.696GiB","percent":"10.93%"},"cpu":"0.45%"}
{"container":"22ed88ee3afa","memory":{"raw":"525.1MiB / 3.696GiB","percent":"13.87%"},"cpu":"0.94%"}
结果说明:
默认情况下,stats
命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl + c
。下面是输出的主要内容:
字段 | 说明 |
---|---|
CONTAINER | 以短格式显示容器的 ID。 |
CPU % | CPU 的使用情况。 |
MEM USAGE / LIMIT | 当前使用的内存和最大可以使用的内存。 |
MEM % | 以百分比的形式显示内存使用情况。 |
NET I/O | 网络 I/O 数据。 |
BLOCK I/O | 磁盘 I/O 数据。 |
PIDS | PID 号。 |
自定义的格式中可以使用的所有占位符:
点位符 | 说明 |
---|---|
.Container | 根据用户指定的名称显示容器的名称或 ID |
.Name | 容器名称 |
.ID | 容器 ID |
.CPUPerc | CPU 使用率 |
.MemUsage | 内存使用量 |
.NetIO | 网络 I/O |
.BlockIO | 磁盘 I/O |
.MemPerc | 内存使用率 |
.PIDs | PID 号 |
四、数据卷
数据卷(Data Volumes):就是将容器内数据直接映射到本地主机环境的指定文件目录之中,可以理解为容器挂载一个虚拟数据卷然后映射到一个主机目录中
在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着容器的结束而结束),就需要将数据从宿主机挂载到容器中。
1. 挂载的类型
(1)volume(最常用)
分为匿名挂载和具名挂载:
-
匿名挂载:
-v 容器内路径
docker run -v /ect/nginx nginx
-
具名挂载:
-v 卷名字:容器内路径
docker run -v nginxConfig:/ect/nginx nginx
可以通过 docker inspect 容器名
或者 docker volume inspect 卷名
来查看到挂载信息:
"Mounts": [
{
"Type": "volume", //挂载的类型
"Name": "nginxConfig",//卷的名字
"Source": "/var/lib/docker/volumes/nginxConfig/_data",//卷在本地的位置(这种方式挂载的卷位置默认都在/var/lib/docker/volumes/_data目录下)
"Destination": "/ect/nginx",//容器内目录
"Driver": "local",
"Mode": "z",
"RW": true, //支持读写
"Propagation": ""
}
],
(2)bind(较常用)
使用方法:-v /本地目录:容器目录
docker run -v /home/test:/home centos
当本地不存在 /home/test
目录时,Docker
会自动创建
可以通过 docker inspect 容器名
来查看到挂载信息:
"Mounts": [
{
"Type": "bind", //挂载的类型
"Source": "/home/test", //本地目录
"Destination": "/home", //容器内目录
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
但是,bind
在不同的宿主机系统时不可移植的,比如Windows
和Linux
的目录结构是不一样的,bind
所指向的host
目录也不能一样。这也是为什么bind
不能出现在Dockerfile
中的原因,因为这样Dockerfile
就不可移植了。
2. docker volume(卷管理命令)
# docker volume volume_name // 创建一个自定义容器卷
# docker volume ls // 查看所有容器卷
# docker volume inspect volume_name // 查看指定容器卷详情信息
# docker volume rm volume_name // 删除自定义数据卷
3. 权限
-
ro
:readonly
,表示只读,表示这个路径只能通过本地去访问,容器内部是无法访问的docker run -d -P --name nginx01 -v /ect/nginx:ro nginx
-
rw
:readwrite
,表示可读可写,默认。docker run -d -P --name nginx01 -v /ect/nginx:rw nginx
4. 数据卷容器(–volumes-from)
数据卷容器(Data Volume Containers):用专门的容器来挂载数据卷,其他容器通过挂载这个父容器来实现数据共享,这个专门挂载数据卷的容器就是数据卷容器,简单的总结就是有一个容器来专门管理数据的持久化和容器之间数据共享
如果我们经常需要多个容器之间进行数据共享,我们需要用到命令 “--volumes-from
”
具体实例:
-
我们从仓库拉一个 centos 的容器镜像
docker pull centos
-
然后运行这个镜像,创建 mycentos 容器,并创建一个数据卷挂载到
/mydata
docker run -it -v /mydata --name mycentos centos
-
再运行两个容器,在这两个容器中使用
--volumes-from
来继承 mycentos 容器中的数据卷docker run -it --volumes-from mycentos --name soncentos1 centos docker run -it --volumes-from mycentos --name soncentos2 centos
此时,容器 soncentos1 和 soncentos2 都挂载同一个数据卷到相同的 /mydata 目录。三个容器任何一方在该目录下的写入数据,其他容器都可以看到。
--volumes-from
后面的容器(mycentos)就是数据卷容器。可以通过数据卷容器创建多个子容器(soncentos1,soncentos2),即便是删除了初始的数据卷容器mycentos
,或是删除了其它容器,但只要是有容器在使用该数据卷,那么它里面的数据就不会丢失!(除非是没有容器在使用它们)
五、网络
1. docker0
通过 ip addr 命令可以看到,docker 会生成一个网卡 docker0
每启动一个 docker 容器,docker 就会给容器分配一个 ip,默认使用桥接模式,使用的技术是 veth-pair
启动一个 redis 容器,可以看到主机上多了一个网卡,并与容器内网卡对应
容器内网卡:
主机网卡:
veth-pair
就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连,正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
不同容器是可以互相访问的,docker0 可以理解为一个路由器
容器删除,对应的网卡也会被删除
2. docker network
ls:查看网络
docker 默认有三个网络:
create:创建网络
创建自定义网络,如果不指定类型,默认创建类型为 bridge
类型
- 命令:
docker network create [OPTIONS] NETWORK
名称,速记 | 默认 | 描述 |
---|---|---|
-d, --driver | bridge | 指定网络类型 |
–subnet | 表示网段的CIDR格式的子网 | |
–gateway | 网关 |
- 例子:
-
创建自定义网络
docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
-
启动容器并使用
--net
加入网络docker run -d -P --name redis-net-01 --net mynet redis:alpine docker run -d -P --name redis-net-02 --net mynet redis:alpine
在 mynet 网络中,容器之间可以通过容器名来相互访问:
-
其它命令
可以通过 --help
来查看详细操作(例如:docker network disconnect --help
)
命令 | 说明 |
---|---|
connect | 将容器加入网络 |
disconnect | 容器从网络中断开连接 |
inspect | 查看网络的详细信息 |
prune | 删除所有未使用的网络 |
rm | 删除网络 |
3. 网络隔离
docker 中的网络中相互隔离的,这样做的好处就是,不同的集群使用不同的网络,保证集群是安全和健康的。
两个网络中的容器是隔开的,无法互相访问,通过 docker network connect
来使 A 网络中的容器加入 B 网络,从而实现 A 网络中的容器对 B 网络的访问。原理:在容器中新增一个 B 网络的 IP,即一个容器,多个 IP
六、DockerFile
1. 基础知识
这部分参考:Docker学习笔记(五)–dockerfile
-
每个保留关键字(指令)都是必须是大写字母
-
Dockerfile 文件执行从上到下顺序执行
-
#
表示注释 -
每一个指令都会创建提交一个新的镜像层,并提交
-
Docker
镜像是由特殊的文件系统叠加而成;最底端是bootfs
,并使用宿主机的bootfs
。一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。当从一个镜像启动容器时,Docker
会在最顶层加载一个读写文件系统作为容器。如下图
2. 基础命令
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定基础镜像 | 指定dockerfile基于那个image构建,一切从这里开始 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的,一般为:姓名 + 邮箱 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令,默认是/bin/sh 格式:RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令,和ENTRYPOINT 配合使用。格式 CMD command param1 param2 或者 CMD ["command", "param1", "param2"] 。可以使用 && 在一个 CMD 中拼接多个命令 |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用,格式ENTRYPOINT ["command", "param1", "param2"] |
COPY | 复制文件 | build 的时候复制文件到image 中 |
ADD | 添加文件 | build 的时候添加文件到image 中,不仅仅局限于当前build 上下文,可以来源于远程服务,如果是压缩文件,会自动解压 |
ENV | 环境变量 | build 的时候设置环境变量,可以在启动的容器的时候,通过-e 覆盖。格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build 的image 哪些目录可以启动的时候挂载到文件系统中。启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口,启动容器的使用-p 来绑定暴露端口。格式:EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录,如果没有创建则自动创建,如果指定 / 使用的是绝对地址;如果不是 / 开头那么是在上一条workdir 的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD 关键字的镜像被继承时,当执行FROM 完成之后,会执行 ONBUILD 的命令,但是不影响当前镜像 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
3. docker build(构建镜像)
首先要先写好 Dockerfile 文件,然后使用 docker build 命令来构建镜像
-
命令:
docker build [OPTIONS] PATH
-
常用可选项:
名称,速记 默认 描述 -f
指定要使用的Dockerfile路径。如果文件为当前目录下的 Dockerfile
(文件名叫这个),则可以不用使用-f
指定--tag
,-t
镜像的名字及标签,通常 name:tag
或者name
格式;可以在一次构建中为一个镜像设置多个标签。 -
例子,对官方的 centos 进行修改(加入 vim 和 net-tools),构建自己的centos:
-
先写好
dockerfile
文件:docker hub 中 99% 的镜像都是从scratch
(FROM scratch)基础镜像开始的,然后再配置需要的软件和一些配置进行构建的。这里直接从centos
开始构建,文件名字叫mydockerfile-centos
:FROM centos MAINTAINER xiaomanong<zyx1260168395> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "---end---" CMD /bin/bash
-
使用 docker build 命令构建镜像
# 不要忘了最后一个点 '.' ,表示当前路径 docker build -f mydockerfile-centos -t mycentos:0.1 .
-
然后使用
docker images
便可以查看到自己的镜像
-
4. docker history(查看镜像的创建历史)
-
命令:
docker history [OPTIONS] IMAGE
-
常用可选项:
名称,速记 默认 描述 -H
true
以可读的格式打印镜像大小和日期 -
例子:查看 5.3 中刚创建的 mycentos:
# 显示的构建过程是自下而上的
[root@localhost zyx]# docker history mycentos
IMAGE CREATED CREATED BY SIZE COMMENT
f006331eed43 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
844dae209483 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
9047ac00cd0f 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
9052f658149b 4 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
216accbf3204 4 minutes ago /bin/sh -c yum -y install net-tools 22.8MB
f036dff75a56 4 minutes ago /bin/sh -c yum -y install vim 57.2MB
86e8dcdb7221 5 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
58fa1de6f554 5 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
613d715c859b 5 minutes ago /bin/sh -c #(nop) MAINTAINER xiaomanong<zyx… 0B
470671670cac 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 5 months ago /bin/sh -c #(nop) ADD file:aa54047c80ba30064… 237MB
5. CMD 与 ENTRYPOINT 的区别
CMD
:指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代ENTRYPOINT
:指定这个容器启动时要运行的命令,可以追加命令
首先,这里有两个 dockerfile
分别构建成的镜像:
-
镜像
cmdtest
:FROM centos CMD ["ls","-a"]
-
镜像
enttest
:FROM centos ENTRYPOINT ["ls","-a"]
然后使用 docker run 命令分别创建这两个镜像的容器:
-
对镜像
cmdtest
做测试:# 1. 不加命令运行,会执行 dockerfile 中的 CMD 命令 [root@localhost zyx]# docker run --rm cmdtest . .. # 2. 加上命令后,会替换 dockerfile 中默认的 CMD 命令 [root@localhost zyx]# docker run --rm cmdtest ls -al total 56 drwxr-xr-x. 1 root root 4096 Jun 16 14:30 . drwxr-xr-x. 1 root root 4096 Jun 16 14:30 .. # 3. 如果是对 CMD 命令添加参数,则会报错 [root@localhost zyx]# docker run --rm cmdtest -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
-
对镜像
enttest
做测试:# 1. 不加命令运行,会执行 dockerfile 中的 ENTRYPOINT 命令,与 CMD 效果相同 [root@localhost zyx]# docker run --rm enttest . .. # 2. 由于 ENTRYPOINT 是追加命令,启动容器时实际执行的命令为:ls -a ls -al,故报错 [root@localhost zyx]# docker run --rm enttest ls -al ls: cannot access 'ls': No such file or directory # 3. 启动容器时实际执行的命令:ls -a -l [root@localhost zyx]# docker run --rm enttest -l total 56 drwxr-xr-x. 1 root root 4096 Jun 16 14:28 . drwxr-xr-x. 1 root root 4096 Jun 16 14:28 ..
6. 实战:使用自己的Tomcat压缩包来制作Tomcat镜像
这里使用的是自己的 Tomcat
压缩包和JDK8
压缩包来制作 Tomcat
镜像
-
首先将这两个压缩包发送到服务器上,然后在同一目录下编写 Dockerfile 文件:
FROM centos MAINTAINER xiaomanong<zyx1260168395> ADD jdk-8u121-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.0.M26.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_121 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.0.M26 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.0.M26 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.0.M26/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.0.M26/logs/catalina.out
-
构建镜像:
docker build -f Dockerfile -t mytomcat .
-
启动一个该镜像的容器,使用
-v
来挂载目录:docker run -d -p 8080:8080 -v /home/test/mytomcat/webapps:/usr/local/apache-tomcat-9.0.0.M26/webapps -v /home/test/mytomcat/logs:/usr/local/apache-tomcat-9.0.0.M26/logs --name mytomcat mytomcat
7. 发布镜像到docker hub
(1)登录 ducker hub
在 ducker hub
上注册自己的账号,然后通过命令行来登录 docker hub
- 命令:
docker login [OPTIONS] [SERVER]
- 常用可选项:
名称,速记 默认 描述 --password
,-p
密码 --username
,-u
用户名
(2)docker tag 标记镜像
-
命令:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
注意:TARGET_IMAGE
格式,如下图(要使用自己docker hub
的用户名,不然会报错):
-
将刚制作的 mytomcat 镜像标记:
docker tag mytomcat 1260168395/mytomcat:1.0
(3)发布镜像到docker hub:
-
命令:
docker push [OPTIONS] NAME[:TAG]
-
将 mytomcat 镜像发送到 docker hub 上:
docker push 1260168395/mytomcat:1.0
(4)登出 docker logout
- 命令:
docker logout [SERVER]
8. 发布镜像到阿里云容器服务
-
登录阿里云(https://www.aliyun.com/),找到容器与镜像服务(找不到的可以参考 2.2 配置阿里云镜像加速)
-
创建命名空间
-
创建镜像仓库
- 点击创建镜像
- 填写仓库信息
- 选择代码源,这里使用的是本地仓库这个代码源:
- 点击创建镜像
-
发布镜像
点击刚创建好的镜像仓库,查看镜像仓库的详细信息,仓库中会如何提交镜像到这个仓库的说明与命令,自行参考自己的即可。
七、Docker Compose
Docker Compose 官方文档:https://docs.docker.com/compose/
1. 简介
- 前面我们使用
Docker
的时候,定义Dockerfile
文件,然后使用docker build
、docker run
等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知 - 使用
Docker Compose
可以轻松、高效的管理多个容器,它是一个用于定义和运行多容器Docker
的应用程序工具
使用 Compose 基本上是一个三步过程:
-
首先使用
Dockerfile
定义自己的环境,以便可以在任何地方复制。 -
在
docker-compose.yml
文件中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。 -
执行
docker-compose up
命令,启动并运行整个应用程序。
一个 docker-compose.yml
看起来像这样:
version: "3.8"
services:
web:
build: . # 使用当前目录中的 Dockerfile 构建 web 镜像
ports: # 暴露端口
- "5000:5000"
volumes: # 卷挂载
- .:/code
- logvolume01:/var/log
links: # 与下面定义的 redis 服务(容器)连接
- redis
redis:
image: redis # 使用 redis 镜像
volumes:
logvolume01: {} # 定义卷名
2. 安装
官方文档,这里有各个系统的安装方法:https://docs.docker.com/compose/install/
Linux(Centos7)安装
-
下载
可以选择从官网下载或者是 DaoCloud 下载# 这里是1.27.4版本的,其它版本要替换链接中的1.27.4 # 这是官网的地址 sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 这是 DaoCloud 地址 curl -L https://get.daocloud.io/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
-
将可执行权限应用于二进制文件
sudo chmod +x /usr/local/bin/docker-compose
-
执行
docker-compose version
查看是否安装成功
3. 快速开始
这是来自官网的一个入门小例子 :https://docs.docker.com/compose/gettingstarted/
我这里对官网的例子稍做修改,使例子更加简洁
-
为项目创建目录:
mkdir composetest cd composetest
-
在刚创建的项目目录中创建一个名为
app.py
的文件,并粘贴如下代码:import time import redis from flask import Flask app = Flask(__name__) # 注意这里的小细节,访问 redis 时,host 并不是ip地址,而是域名(服务名) redis cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: # 每访问一次,通过 redis 自增 1 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) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
-
在项目目录中创建另一个名为
requirements.txt
的文件,并粘贴如下代码:flask redis
-
在项目目录中,创建一个名为
Dockerfile
的文件,并粘贴以下内容:FROM python:3.7-alpine ADD . /code WORKDIR /code RUN pip install -r requirements.txt CMD ["python", "app.py"]
-
在项目目录中创建一个名为
docker-compose.yml
的文件,然后粘贴以下内容:version: "3.8" services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine"
-
在项目目录中,通过
docker-compose up
运行来启动应用程序。 -
在浏览器中输入
http://localhost:5000
以查看该应用程序正在运行。
-
可以看到,启动了两个服务:
默认的容器名:
文件名_服务名_副本数量
-
查看网络
Docker Compose 会自动生成一个网络,启动的服务都在这个网络中,所以服务之间可以通过域名(服务名)访问
-
其它命令
-
后台运行
docker-compose up -d
-
查看当前正在运行的服务
docker-compose ps
-
如果是后台运行的话,使用下面的命令停止
注意:要在启动时的那个目录下执行
docker-compose stop
-
4. yaml配置文件
官方文档:https://docs.docker.com/compose/compose-file/
菜鸟教程:https://www.runoob.com/docker/docker-compose.html
version:版本
指定本 yml 依从的 compose 哪个版本制定的。向下兼容,最新的是 3.8
services:多个容器集合
build:指定Dockerfile
指定 Dockerfile 的上下文路径或者是一个对象,该对象可以指定 Dockerfile 的参数:
version: "3.7"
services:
webapp:
build: ./dir
webapp2:
build:
context: ./dir # 上下文路径
dockerfile: Dockerfile-alternate # 指定构建镜像的 Dockerfile 文件名
args: # 添加构建参数,这是只能在构建过程中访问的环境变量
buildno: 1
labels: # 设置构建镜像的标签
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
target: prod # 多层构建,可以指定构建哪一层
command:覆盖容器启动后默认执行的命令
command: ["bundle", "exec", "thin", "-p", "3000"]
container_name:自定义生成的容器名称
自定义生成的容器名称,而不是生成的默认名称
container_name: my-web-container
depends_on:设置依赖关系
version: "3.8"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
注意:web 服务不会等待 redis db 完全启动 之后才启动。
docker-compose up :以依赖性顺序启动服务。示例中,先启动 db 和 redis ,才会启动 web。
docker-compose up SERVICE :自动包含 SERVICE 的依赖项。示例中,docker-compose up web 还将创建并启动 db 和 redis。
docker-compose stop :按依赖关系顺序停止服务。示例中,web 在 db 和 redis 之前停止。
dns:配置 dns 服务器
配置 dns 服务器,可以是一个值或列表
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
dns_search:配置 DNS 搜索域
配置 DNS 搜索域,可以是一个值或列表
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
env_file:从文件中获取环境变量
从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量。可以是单个值或列表的多个值。
env_file: .env
env_file:
- ./common.env
environment:环境变量配置
添加环境变量配置,可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。
environment:
RACK_ENV: development
SHOW: 'ture'
entrypoint:启动容器后执行的命令
会覆盖容器默认的 entrypoint
或者 dockerFile
中的 CMD
命令。
entrypoint: /code/entrypoint.sh
也可以是以下格式:
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
expose:暴露端口
暴露端口,只将端口暴露给连接的服务,而不暴露给主机,仅可以指定内部端口为参数
expose:
- "3000"
- "8000"
extra_hosts:添加主机名映射
添加主机名映射,类似 docker client --add-host。
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:
162.242.195.82 somehost
50.31.209.229 otherhost
image:指定服务所使用的镜像
image: java
image: a4bc65fd # 镜像id
links:链接到另一个服务中的容器
链接到另一个服务中的容器。指定服务名称和链接别名(“SERVICE:ALIAS”),或者仅指定服务名称。
可以使用与别名相同的主机名访问链接服务的容器,如果未指定别名,则可以使用服务名。
version: "3"
services:
web:
links:
- "db"
- "db:database"
db:
image: postgres
logging:服务的日志记录配置
driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项
driver: "json-file"
driver: "syslog"
driver: "none"
-
仅在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小。
logging: driver: json-file options: max-size: "200k" # 单个文件大小为200k max-file: "10" # 最多10个文件
当达到文件限制上限,会自动删除旧得文件。
-
syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。
logging: driver: syslog options: syslog-address: "tcp://192.168.0.42:123"
network_mode:设置网络模式
使用与 docker client--network
参数相同的值,以及特殊形式 service:[service name]
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
networks:配置容器连接的网络
配置容器连接的网络,引用顶级 networks 下的条目 。
services:
some-service:
networks:
some-network:
aliases:
- alias1
other-network:
aliases: # 同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。
- alias2
networks:
some-network:
# Use a custom driver
driver: custom-driver-1
other-network:
# Use a custom driver which takes special options
driver: custom-driver-2
ports:对外暴露的端口定义,和 expose 对应
ports: # 暴露端口信息 - "宿主机端口:容器暴露端口"
- "5000:5000"
- "8763:8763"
volumes:卷挂载路径
将主机的数据卷或着文件挂载到容器里。使用方法:主机路径或卷名 : 容器路径
(在顶级的 volumes
中定义卷名)
version: "3.8"
services:
db:
image: postgres:latest
volumes:
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
- "dbdata:/var/lib/postgresql/data"
volumes:
dbdata:
restart: always:设置容器自启动
version: "3.8"
services:
mysql:
image: mysql:5.7
volumes:
- "/mydata/mysql/log:/var/log/mysql"
- "/mydata/mysql/data:/var/lib/mysql"
- "/mydata/mysql/conf:/etc/mysql"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "root"
restart: always
redis:
image: redis
volumes:
- "/mydata/redis/data:/data"
- "/mydata/redis/conf/redis.conf:/etc/redis/redis.conf"
ports:
- "6379:6379"
entrypoint: ["redis-server", "/etc/redis/redis.conf"]
restart: always
5. 常用命令
官方文档:https://docs.docker.com/compose/reference/build/
命令 | 说明 | 举例 |
---|---|---|
ps | 列出所有运行容器 | docker-compose ps |
logs | 查看服务日志输出 | docker-compose logs |
port | 打印绑定的公共端口,下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口 | docker-compose port eureka 8761 |
build | 构建或者重新构建服务 | docker-compose build |
start | 启动指定服务已存在的容器 | docker-compose start eureka |
stop | 停止已运行的服务的容器 | docker-compose stop eureka |
rm | 删除指定服务的容器 | docker-compose rm eureka |
up | 构建、启动容器 | docker-compose up 开启容器之前先构建镜像:docker-compose up --build 后台运行:docker-compose up -d |
kill | 通过发送 SIGKILL 信号来停止指定服务的容器 | docker-compose kill eureka |
pull | 下载服务镜像 | |
scale | 设置指定服务运行容器的个数,以 service=num 形式指定 | docker-compose scale user=3 movie=3 |
run | 在一个服务上执行一个命令 | docker-compose run web bash |
八、可视化
1. portainer
文档:https://www.portainer.io/documentation/
跟着文档走就可以了,以下是对我的操作做个笔记
- 安装
docker volume create portainer_data docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
- 浏览器访问
9000
端口即可。
九、示例
1. 部署Mysql
-
服务器可以连接外网,直接从仓库 pull 镜像
docker pull mysql:5.7
-
服务器不可以连接外网,则先从一个有网络的电脑下载 mysql 镜像,然后再将镜像保存到本地,再把镜像发送到没有网的服务器,最后通过 docker 加载镜像即可:
-
保存镜像到本地文件
docker save -o mysql5.7 mysql:5.7
-
把镜像拷贝到无网络的电脑,然后通过docker加载镜像即可。
sudo docker load -i mysql5.7
-
-
启动 mysql 容器
docker run -dit -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 --name="mysql01" mysql:5.7
2. 部署Nginx
-
搜索镜像,可以使用
docker search
命令去搜索,我更推荐去 Docker Hub(https://hub.docker.com/) 上去搜索,第一次进入 Docker Hub 需要注册一下,注册登录之后直接搜索Nginx:
点进去之后,会有版本信息,镜像的使用(配置)等一些信息。 -
拉取镜像,若没有网络,则处理方式与 Mysql 镜像相同
docker pull nginx
-
启动临时容器,获取 nginx 的配置文件
# 先随便启动一个 Nginx 容器
docker run --name nginx-tmp -d -p 80:80 nginx
# 将nginx容器中的nginx目录复制到本机的/mydata/nginx/conf目录
docker container cp nginx:/etc/nginx /mydata/nginx/conf
# 复制的是nginx目录,将该目录的所有文件移动到 conf 目录
mv /mydata/nginx/conf/nginx/* /mydata/nginx/conf/
# 删除多余的 /mydata/nginx/conf/nginx目录
rm -rf /mydata/nginx/conf/nginx
# 停止运行 nginx 容器
docker stop nginx-tmp
# 删除 nginx 容器
docker rm nginx-tmp
- 启动 nginx 容器
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf/:/etc/nginx \
-d nginx:1.10
--restart=always
- 测试 nginx
echo '<h1><a target="_blank" href="https://github.com/zsy0216/guli-mall">nginx配置成功</a></h1>' \
>/mydata/nginx/html/index.html
浏览器访问 ip:80,看到上面配置的 index.html 页面,则 nginx 启动成功
3. 部署Tomcat
-
同样,先上 Docker Hub 上搜索
Tomcat
,然后找到对应的版本进行pull
。docker pull tomcat:9.0
-
启动一个
Tomcat
容器docker run -d -p 8080:8080 --name tomcat01 tomcat
-
Tomcat
容器的一些配置Tomcat
容器中,Tomcat 的位置在/usr/local/tomcat
,其中,webapps
文件夹中内容为空,原本的内容全在webapps.dist
文件夹下。- 配置文件位于
/usr/local/tomcat/conf/
-
webapps
文件夹下有内容后,通过浏览器访问来查看Tomcat
是否配置成功
4. docker-compose使用案例
注意:nginx 要先启一个临时的容器,获取配置文件,放到要挂载的目录,再启动正式的 nginx
version: "3.8"
services:
mysql:
image: mysql:5.7
volumes:
- "/mydata/mysql/log:/var/log/mysql"
- "/mydata/mysql/data:/var/lib/mysql"
- "/mydata/mysql/conf:/etc/mysql"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "root"
restart: always
redis:
image: redis
volumes:
- "/mydata/redis/data:/data"
- "/mydata/redis/conf/redis.conf:/etc/redis/redis.conf"
ports:
- "6379:6379"
entrypoint: ["redis-server", "/etc/redis/redis.conf"]
restart: always
nacos:
image: nacos/nacos-server:2.0.1
ports:
- "8848:8848"
environment:
MODE: "standalone"
restart: always
nginx:
image: nginx:1.18.0
ports:
- "80:80"
volumes:
- "/mydata/nginx/conf:/etc/nginx"
- "/mydata/nginx/html:/usr/share/nginx/html"
- "/mydata/nginx/logs:/var/log/nginx"
restart: always
elasticsearch:
image: elasticsearch:7.4.2
ports:
- "9200:9200"
- "9300:9300"
environment:
discovery.type: "single-node"
ES_JAVA_OPTS: "-Xms64m -Xmx512m"
volumes:
- "/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml"
- "/mydata/elasticsearch/data:/usr/share/elasticsearch/data"
- "/mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins"
restart: always
kibana:
image: kibana:7.4.2
ports:
- "5601:5601"
environment:
ELASTICSEARCH_HOSTS: "http://10.211.55.12:9200"
restart: always