Docker服务启动时会首先在主机上自动创建一个docker0虚拟网桥,实际上是一个Linux网桥,它在内核层连通了其它的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。网桥可以理解为一个软件交换机,负责挂载其上的接口之间进行包转发。使用 ifconfig命令可以查看:
同时,Docker随机分配一个本地未占用的私有网段中的一个地址给docker0接口。比如典型的172.17.0.0/16,掩码为255.255.0.0.此后启动的容器内的网口也会自动分配一个该网段的地址。
当创建一个Docker容器的时候,同时会创建一对veth pair互联接口。当任一个接口发送包时,另一个接口自动收到相同的包。互联接口的一端位于容器内,即eth0;另一端在本地被挂载到docker0网桥,名称以veth开头。通过这种方式,主机可以与容器通信,容器之间也可以互相通信。如此一来,Docker就创建了在主机和所有容器之间一个虚拟共享网络,如下图:
docker0就像是一个路由器,一个容器跟另一个容器通信要经过docker0路由器,而不是直接通信。所有网络在不指定网络的情况下,都是docker0路由的,docker0会给我们的容器分配一个默认的可用IP。
下面的命令可以在运行容器时指定:
其中 --net 支持以下五种模式:
-h参数:
当我们启动一个容器时,默认将容器ID的前几位作为容器的主机名:
可以在启动容器时指定hostname:
–link参数:容器互联
如果我们想要通过在一个容器中使用容器名来和另一个容器进行通信,就可以指定-link参数:
由于官方的Ubuntu镜像中没有ping以及ifconfig命令,因此自己构建了一个带有这两个软件的ubuntu。
如上图所示,在没有使用–link参数时使用ubuntu2容器通过容器名来ping ubuntu1是ping不通的,但是使用了–link之后就可以了。但是,–link是单向的,也就是说反过来使用ubuntu1来ping ubuntu3依然是不通的。
--link的本质就是在创建容器时,添加了一个所连接容器的主机名到容器内/etc/hosts文件中。这样,新建容器可以直接使用主机名与所连容器通信:
上面使用容器互联(–link参数)可以达到使用容器名来进行通信,但是是单向的,非常不方便。我们可以使用自定义网络来达到更方便的互联。
docker网络相关命令:
docker network
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network 将容器接入到网络
create Create a network 创建一个网络
disconnect Disconnect a container from a network 把容器从网络上断开
inspect Display detailed information on one or more networks 查看网络详细信息
ls List networks 列出所有网络
prune Remove all unused networks 清理无用的网络资源
rm Remove one or more networks 删除一个网络
查看所有docker网络:
命令: docker network ls
网络模式:
自定义网络:
docker0网络特点:默认的,域名不能访问,–link可以打通。
创建网络命令:
docker network create
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
-d, --driver string Driver to manage the Network (default "bridge") 网络驱动类型,如bridge或overlay
--gateway strings IPv4 or IPv6 Gateway for the master subnet 网关
--subnet strings Subnet in CIDR format that represents a network segment 网络地址段,CIDR格式,如 172.17.0.0/16
# 还有一些其它参数上面没有列出来 可以使用 docker network create --help 来查看
# 后面的参数也可以不指定,让docker自己配置
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
使用docker network ls 来查看所有的docker网络,可以使用docker inspect来查看网络的详细信息:
创建网络之后,在启动容器时就可以指定使用我们自己的网络:
docker run -id --name ubuntu1 --net=mynet myubuntu
使用docker inspect ubuntu1 查看容器的网络:
使用自己创建的网络的容器都是互通的,可以直接使用容器名来通信:
我么自定义的网络docker都已经帮我们维护好了对应的关系,推荐使用这种方式。
接入网络:
connect命令将一个容器连接到一个已存在的网络上。连接到网络上的容器可以跟同一网络中其它容器互通,同一个容器可以接入多个网络。也可以在执行docker run命令时通过–net参数指定容器启动后自动接入的网络。
假设我们创建了两个网络,在两个网络中分别运行了两个容器。在同一个网络中的容器直接可以直接通信,但是在不同网络中的两个容器时不能直接通信的。如果要想它们实现通信,可以将一个容器连接到另一个网络:
使用的命令:
docker network connect
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
例如:
docker network connect mynet1 ubuntu1_2
使用docker inspect mynet1来查看网络相关信息:
发现ubuntu1_2被加入了mynet1中,而且获得了第二个ip:172.18.0.4
一个容器两个IP,就像是一个公网IP,一个私网IP。
# 下载docker compose
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -output /usr/local/bin/docker-compose
# 给docker compose赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 查看版本
docker-compose -v
至于Docker Compose是什么,能干什么,先不多BB。先上一个案例:使用Docker Compose安装Wordpress来搭建个人博客。官方文档:Quickstart: Compose and WordPress | Docker Documentation
步骤如下:
1.创建一个文件夹以及一个名为docker-compose.yml的文件
mkdir ~/wordpress
cd ~/wordpress
vim docker-compose.yml
2.将下面的内容copy到docker-compose.yml中
version: "3.3"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {
}
wordpress_data: {
}
3.执行下面命令,构建运行
docker-compose up -d
4.等待构建运行成功,打开浏览器输入网址:http://宿主机ip:8000,就可以看到下面页面,选择语言、然后填一些信息、创建账号。如果访问不了,看一下是不是防火墙的问题,如果是阿里云等云服务器要在安全组中开启8000端口。
5.然后就可以看到下面页面,至此博客搭建完毕。可以自己设置博客的布局了!!!
在部署一个项目时,我们的项目可能依赖于多种其它软件,例如mysql、redis等数据库、nginx反向代理等。如果这些软件都使用docker run来运行起来就会比较麻烦。这时就可以使用docker compose来解决。
Compose项目是Docker官网的开源项目,负责实现对基于Docker 容器的多应用服务的快速编排。Compose定位是“定义和运行多个Docker容器的应用”。
使用Dockerfile模板文件可以让用户很方便地定义一个单独地应用服务器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务地情况。例如要实现一个Web项目,除了Web服务器本身,往往还需要再加上后端地数据库服务容器,甚至还包括前端地负载均衡容器等。
Docker Compose恰好满足了这样地需求。它允许用户通过一个单独的docker-compose.yml模板文件来定义一组相关联的容器应用为一个服务栈。
Docker Compose中有几个重要的概念:
官网文档:docker compose | Docker Documentation
模板文件是使用Compose的核心,默认模板文件名称为docker-compose.yml,格式为YAML格式。
例如下面的模板文件:
version: "3"
services:
webapp:
image: examples/web
deploy:
replicas: 2
resources:
limits:
cpus: "0.1"
memory: 100M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- mynet
volumes:
- mynet
networks:
mynet:
version 定义了版本信息。
services下面可以定义多个服务,之下是服务名称,次级元素为服务容器的配置信息。
注意每个服务都必须通过image指令指定镜像或build指令(需要Dockerfile)等来自动构建生成镜像。如果使用build指令,在Dockerfile中设置的选项(例如:CMD、EXPOSE、VOLUME、ENV等)将自动被获取,无需再docker-compose.yml中再次设置。
docker compose可以分为三层:
# 第一层,版本
version: ""
# 第二层,服务
services:
服务1:
image:
networks:
ports:
...
服务2:
build
networks:
ports:
depends_on:
服务3:
...
...
# 第三层 其它配置,例如 networks, volumes, 全局配置 ...
networks:
volumes:
命令列表如下:
命令 | 功能 |
---|---|
build | 指定Dockerfile所在文件夹的路径 |
command | 覆盖容器启动后默认执行的命令 |
container_name | 指定容器名称 |
devices | 指定设备映射关系 |
depends_on | 指定多个服务器之间的依赖关系 |
dockerfile | 指定额外的编译镜像的Dockerfile文件 |
entrypoint | 覆盖容器中默认的入口命令 |
env_file | 从文件中获取环境变量 |
environment | 设置环境变量 |
expose | 暴露端口,但不映射到宿主机,只被连接的服务访问 |
image | 指定为镜像名称或镜像ID |
labels | 为容器添加Docker元数据信息 |
links | 链接到其它服务中的容器 |
network_mode | 设置网络模式 |
networks | 所加入的网络 |
ports | 映射端口 |
ulimits | 指定容器的ulimits限制值 |
volumes | 数据卷所挂载路径设置 |
restart | 指定重启策略 |
deploy | 指定部署和运行时的容器相关配置。该命令只在Swarm模式下生效,且只支持docker stack deploy命令部署 |
下面介绍一些常用指令用法:
1.build
指定Dockerfile所在文件夹的路径(可以时绝对路径,或者相对docker-compose.yml文件的路径)。Compose将会利用它自动构建应用镜像,然后使用这个镜像,例如:
version: "3" # 版本
services:
app: # 服务名
build: /path/to/build/dir # dockerfile所在目录
# 注意再冒号后有一个空格
2.image
指定为镜像名称或镜像ID。如果镜像再本地不存在,Compose将会尝试拉取这个镜像。例如:
image: ubuntu
image: nginx
3.container_name
指定容器名称。默认将会使用”项目名称_服务名称_序号“这样的格式。目前不支持再Swarm模式中使用。例如:
container_name: docker_web_container
4.depends_on
指定多个服务之间的依赖关系。启动时,会先启动被依赖的服务。例如,可以指定依赖于db服务:
depends_on: mysql
5.environment
设置环境变量,可以使用数组或字典两种格式。只给定名称的变量会自动获取运行Compose主机上对应变量的值,可以用来防止泄露不必要的数据。例如:
environment:
RACK_ENV: development
SESSION_SECRET:
# 或者
environment:
- RACK_ENV=development
- SESSION_SERET
6.expose
暴露端口,但不映射到宿主机,只被链接的服务访问。尽可以指定内部端口为参数,如下所示:
expose:
- "3000"
- "8000"
7.networks
所加入的网络。需要再顶级的networks字段中定义具体的网络信息。
例如,指定web服务的网络为web_net,并添加服务在网络中的别名为web_app:
services:
web:
networks:
web_net:
aliases: web_app
ipv4_address: 172.16.0.10
networks:
web_net:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
subnet: 172.16.0.0/24
8.ports
映射端口信息。例如:
ports:
- "3000"
- "8000:8000"
# 或者
ports:
- target: 80
- published: 8080
- protocol: tcp
9.volumes
数据卷所挂载路径设置。可以设置宿主机路径(HOST:CONTAINER)或加上访问模式(HOST:CONTAINER:ro)。该指令支持相对路径。例如:
volumes:
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs/:ro
# 或者更详细的语法
volumes:
- type: volume
source: mydata
target: /data
volumes:
mydata:
执行docker-compose --help来查看帮助。
mgh@ubuntu:~$ docker-compose --help
Define and run multi-container applications with Docker. 使用Docker定义运行多容器的应用
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file #指定使用的compose模板文件,默认为docker-compose.yml
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name #指定项目名称,默认使用所在目录作为项目名称
(default: directory name)
--project-directory PATH Specify an alternate working directory #指定工作目录,默认为compose文件所在路径
Commands:
build Build or rebuild services # 构建或重新构建项目中的服务容器
config Validate and view the Compose file # 校验和查看Compose文件的配置信息
down Stop and remove containers, networks, images, and volumes # 停止服务栈,并删除相关资源
exec Execute a command in a running container # 在一个运行中的容器内执行给定命令
images List images # 列出服务所创建的镜像
kill Kill containers # 通过发送SIGKILL信号来强制停止服务容器
pause Pause services # 暂停服务
port Print the public port for a port binding # 打印某个容器端口所映射的公共端口
ps List containers # 列出项目中目前的所有容器
pull Pull service images # 拉取服务依赖的镜像
push Push service images # 推送服务创建的镜像到镜像仓库
restart Restart services # 重启项目中的服务
rm Remove stopped containers # 删除停止的容器
run Run a one-off command # 在指定服务上执行一个命令
start Start services # 启动已经存在的服务容器
stop Stop services # 停止已经处于运行状态的容器,但不删除
top Display the running processes # 显示服务栈中正在运行的进程信息
unpause Unpause services # 恢复处于暂停状态中的服务
up Create and start containers # 尝试自动完成一系列操作:包括构建镜像,创建服务,启动服务,并关联相关容器等
version Show the Docker-Compose version information # 打印版本信息
接下来使用springboot项目以及redis来构建一个docker compose服务栈:
1、创建一个springboot项目,写一个简单的测试程序:
在application.yml使用redis域名来作为host。
2、写springboot的Dockerfile文件:
FROM java:8
ADD compose_test-0.0.1-SNAPSHOT.jar app.jar # 这里jar包名应该不一样,需要修改
CMD ["java", "-jar", "app.jar"]
3、docker-compose.yml文件:
version: "3" # 版本
services: # 下面有两个服务,分别是web和redis
web: # 服务名
build: . # 使用Dockerfile文件构建
restart: always # 重启模式
networks: # 使用的网络
webapp:
ports: # 映射8080端口
- "8080:8080"
depends_on: # web服务依赖redis服务,在启动时会先启动redis
- redis
redis: # 服务名,可以通过服务名来作为域名通信
image: redis # 使用的镜像
restart: always
networks:
webapp:
ports:
- "6379:6379"
volumes: # 挂载数据卷
- /opt/acme/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
- /opt/acme/redis/data:/data
networks: # 自定义网络,也可以不写,上面也不要写,这样docker会自动创建并使用
webapp:
driver: bridge
4、将springboot项目打包为jar包,创建目录,将jar、Dockerfile、docker-compose.yml放到该目录下:
mkdir ~/compose_test && cd ~/compose_test
5、使用下面命令启动服务栈
docker-compose up -d
# -d参数表示后台启动
6、访问页面
Docker Swarm 是Docker公司推出的官方容器集群平台,基于Go语言实现。作为容器集群管理器,Swarm最大的优势之一就是原生支持Docker API,给用户带来极大的便利。各种基于标准API的工具比如Compose、Docker SDK、各种管理软件,甚至Docker本身都可以很容易的与Swarm集成。
Swarm也采用了典型的“主从”结构,通过Raft协议来在多个管理节点中实现共识。工作节点上运行agent接收管理节点的统一管理和任务分配。用户提交服务请求只需发给管理节点即可,管理节点会按照调度策略在集群中分配节点来运行服务相关任务。
下面先介绍Swarm使用中的一些基本概念:
1、Swarm集群
Swarm集群(Cluster)为一组被统一管理起来的Docker主机。集群是Swarm所管理的对象。这些主机通过Docker引擎的Swarm模式互相沟通,其中部分主机可能作为管理节点(Manager)响应外部的管理请求,其它主机作为工作节点(Worker)来实际运行Docker容器。当然,管理节点也可以运行Docker容器。
当用户使用Swarm集群时,首先要创建一个Swarm集群,然后生成worker节点以及manager节点的token。其它机器可以通过这个token来加入工作节点或管理节点。然后启动一个服务(指定状态、复制个数、网络、存储、暴露端口等),然后通过管理节点发出启动服务的指令,管理节点随后会按照指定的服务规则进行调度,在集群中启动起来整个服务,并确保它正常运行。
2、节点(Node)
节点(Node)是Swarm集群的最小资源单位,每个节点实际上都是一台运行了Docker的主机。Swarm集群中节点分为两种:
3、服务(Service)
一个服务可以由若干个任务组成,每个任务为某个具体的应用。Swarm集群中服务类型也分为两种(可以通过–mode指定):
4、任务
任务是Swarm集群中最小的调度单位,即一个指定应用的容器。Swarm集群中的管理节点会按照调度要求将任务分配到工作节点上。例如指定副本为2时,可能会被分配到两个不同的工作节点上。一旦当某个任务被分配到一个工作节点,将无法被转移到另外的工作节点,即Swarm中的任务不支持迁移。
5、服务的外部访问
Swarm集群中的服务要被集群外部访问,必须要能运行任务的响应端口映射出来。Swarm中支持入口负载均衡的映射模式。该模式下,每个服务都会被分配一个公开端口,该端口在集群中任意节点上都可以访问到,并被保留给该服务。
当有请求发送到任意节点的公开端口时,该节点若没有实际执行服务相关的容器,则会通过路由机制将请求转发给实际执行了服务容器的工作节点。
Swarm集群的主要操作如下(Docker中已经包含了Swarm,所以不需要安装),需要使用多台机器:
# 集群操作
docker swarm COMMAND
COMMANDS:
init Initialize a swarm # 初始化一个swarm集群
join Join a swarm as a node and/or manager # 作为一个worker或manager加入一个swarm集群
join-token Manage join tokens # 生成token
leave Leave the swarm # 离开swarm集群
update Update the swarm # 更新一个swarm集群
# 节点操作
docker node COMMAND
COMMANDS:
inspect Display detailed information on one or more nodes # 查看一个节点或多个节点的信息
ls List nodes in the swarm # 列出swarm集群的节点
promote Promote one or more nodes to manager in the swarm # 提升一个或多个节点为管理节点
ps List tasks running on one or more nodes, defaults to current node # 列出在一个或多个节点上运行的任务,默认显示当前节点
rm Remove one or more nodes from the swarm # 从swarm集群中移除一个或多个节点
update Update a node # 更新一个节点
1.创建集群
docker swarm init [optinos]
Options:
--advertise-addr string Advertised address (format: <ip|interface>[:port]) 指定服务监听的地址和端口
注意返回的token串,这是集群的唯一ID,加入集群的各个节点需要这个信息。
2.获取worker或manager token
也可以通过命令来获取worker或manager的token,通过这个token其它节点可以作为工作节点或管理节点来加入集群。
docker swarm join-token worker # 生成加入工作节点的token
docker swarm join-token manager # 生成加入管理节点的token
3.加入集群
docker swarm join --token
4.查看集群信息
docker info
5.查看节点信息
docker node ls # 只能在管理节点上查看
6.离开集群
docker swarm leave
集群服务相关命令如下:
docker service COMMAND
COMMANDS:
create Create a new service # 创建一个新服务
inspect Display detailed information on one or more services # 查看一个服务的详细信息
logs Fetch the logs of a service or task # 获取服务或任务的日志
ls List services # 列出所有服务
ps List the tasks of one or more services # 查看一个或多个服务的任务列表
rm Remove one or more services # 移除一个或多个服务
rollback Revert changes to a service's configuration # 回滚服务
scale Scale one or multiple replicated services # 对服务进行横向扩展
update Update a service # 更新一个服务
1.创建服务
创建好集群后,可以在管理节点上执行如下命令来快速创建一个应用服务,并指定服务的复制份数:
docker service create [optinos] IMAGE
OPTIONS:
--config config Specify configurations to expose to the service # 指定暴露给服务的配置
-e, --env list Set environment variables # 设置环境变量
--mode string Service mode (replicated, global, replicated-job, or global-job) (default "replicated") # 服务模式,replicated(默认)或global
--name string Service name # 指定服务名
--replicas uint Number of tasks # 指定实例的复制份数
-w, --workdir string Working directory inside the container # 指定工作目录
# 例如 启动有两个副本的redis服务,服务名为test_app
docker service create --replicas 2 --name -p 6379:6379 test_app redis
当前我的swarm集群中有三个节点,一个管理节点,两个工作节点:
发现管理节点和其中一个工作节点上各跑了一个任务。
2.查看服务
docker service ls
3.横向扩展服务
docker service scale SERVICE_ID=NUMBER_OF_TASKS
上面将任务副本扩展为了4个,但是只有3个节点,因此肯定有一个节点跑了两个任务:
发现在管理节点上跑了两个任务
4.查看服务的任务列表
docker service ps SERVICE_ID 或 SERVICE_NAME