01、Docker

Docker实战指南

一、Docker基础

1、为什么是Docker?

在这里插入图片描述

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

1、Docker解决了什么问题

  • 快速交付和部署(镜像与容器)
  • 资源的高效利用和隔离(高密度部署)
  • 轻松的迁移和扩展(一次封装,到处运行)

在这里插入图片描述

2、Docker使用步骤

  • 安装Docker(安装应用商店)
  • 寻找/下载镜像(寻找/下载app)
  • 启动容器(启动应用)
  • 移植(别的手机安装应用商店,继续以前流程)

容器化对比虚拟机

对比属性ContainerVM
隔离性基于进程隔离提供资源的完全隔离
启动时间秒级分钟级
内核共用宿主机内核使用独立内核
占用资源MB级GB级
系统支持容量单机支持上千个容器一般几十个

2、核心概念

在这里插入图片描述

1、Docker 镜像

Docker镜像类似于虚拟机镜像,可以将他理解为一个只读的模板。

2、Docker 容器

Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。容器是从镜像创建来的。容器可以启动、停止、删除,容器之间彼此隔离,互不可见。

可以把容器看做是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子

3、Docker 仓库

Docker仓库是存储镜像的仓库。可以有Public(公有仓库)和Private(私有仓库)。最大的公有仓库是Docker Hub

Docker面向对象
镜像
容器对象

3、安装启动

1、阿里云安装

yum install docker
systemctl enable docker
systemctl start docker

docker -v
docker info

2、标准方式安装

#移除旧版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#安装Docker其他依赖
yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
#设置Docker yum源
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
#安装Docker CE
yum install -y docker-ce docker-ce-cli containerd.io

#安装指定版本的Docker
yum list docker-ce --showduplicates | sort -r
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
#启动Docker
systemctl enable docker
systemctl start docker

二、Docker快速入门

我们以使用Docker的方式安装MySQL为例,快速体会Docker的基本操作

1、镜像操作

1、下载镜像 docker pull mysql

#我们应该先去Docker Hub寻找我们感兴趣的镜像
docker pull image_name[:Tag]
#1、tag一般为镜像的版本,不指定默认下载latest版本
#2、默认镜像是从Docker Hub下载,国内比较慢,推荐使用自己的阿里云加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

在这里插入图片描述

  • 以上下载过程看出,镜像是分层的(Layer)。c499e6d256d6是当前层的唯一id(完整的id为256bit,64个十六进制字符组成)。
  • 不同的镜像如果有相同的层,本地只会存储一份,减小了存储空间
  • 严格说,下载镜像需要制定指定仓库名称,不过从Docker Hub下载的可以忽略前缀。如
    • docker pull **docker.io/library/**mysql:5.7

2、列出镜像 docker images

docker images

在这里插入图片描述

REPOSITORY:来源于哪个仓库

TAG:镜像版本标签信息

IMAGE ID :镜像唯一id

CREATED:镜像最后更新时间

SIZE:镜像大小

3、查看详情 docker inspect

docker inspect image_name[:tag]
docker inspect image_id  

4、删除镜像 docker rmi

docker rmi image_name[:tag] 或者 docker rmi image_id

5、理解镜像

1、疑问一:

Docker每一个容器都是一个完整的这个应用的运行环境。所有应用最起码的基本环境是linux

微服务做成镜像。基本环境就是java环境,

如果我下载了100个镜像,启动了100个容器。100个linux在运行?

UFS:特点;git。增量记录文件改变。分层系统。需要经常读写变化的,只在变化层。

2、容器操作

1、启动容器

#docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 常用选项
-d  守护态运行
-p  Publish a container's port(s) to the host ( container和host端口映射)
-i  以交互模式运行容器,通常与 -t 同时使用
-t  为容器重新分配一个伪输入终端,通常与 -i 同时使用
--name="nginx-lb"  为容器指定一个名称
-v, --volume value  Bind mount a volume (default [])
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name hello-mysql mysql:5.7

#查看所有运行中的容器
docker ps 
#查看所有容器
docker ps -a
#docker create 和 docker run的区别
docker create -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name hello-mysql mysql:5.7
#create新建容器,run新建并启动。create相当于 run -d设置

2、进入容器

#docker exec  [OPTIONS] CONTAINER COMMAND [ARG...]
#Run a command in a running container
docker exec -it hello-mysql /bin/bash	
#尝试连接MySQL
mysql -uroot -p123456
#扩展
docker exec -d hello-mysql touch /hello.txt
docker exec -it hello-mysql mysql -uroot -p

#删除
docker rm container_id/container_name
#查看运行日志
docker logs container_id/container_name

3、其他命令

Docker 命令手册

5、可视化

  • Portainer(先用这个)
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用这个)
#安装rancher-server
docker run --name rancher-server -p 8000:8080 -v /etc/localtime:/etc/localtime:ro  -d  rancher/server
#安装agent
docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11 http://39.101.191.131:8000/v1/scripts/D3DBD43F263109BB881F:1577750400000:7M0yBzCw4XSxJklD7TpysYIpI

三、Docker数据管理

使用Docker过程中,往往需要对数据进行持久化,或者多个容器之间进行数据共享,这就需要我们熟悉容器的数据管理操作

容器中管理数据主要的两种方式:

  • 数据卷(Data Volumes):容器内数据直接映射到本地主机环境
  • 数据卷容器(Data Volumes Containers):使用特定容器维护数据

1、数据卷

将主机操作系统目录直接映射进容器,类似于Linux中的mount。数据卷很好的解耦了容器应用和数据。对数据卷内数据的操作(无论是在本地主机还是容器内),都会立即生效。

docker run -d -p 3307:3306 -v /my/custom:/etc/mysql/conf.d \
-v /my/own/datadir:/var/lib/mysql --restart always --name mysql01 mysql:5.7

-v hostDir:containerDir:hostDir不存在会自动创建,默认权限是rw,也可以改为ro,这样容器内部就无法对数据卷的数据进行修改了。

docker run -d -p 3307:3306 -v /my/custom:/etc/mysql/conf.d:ro \
-v /my/own/datadir:/var/lib/mysql --restart always --name mysql01 mysql:5.7
#数据卷创建
docker volume create [OPTIONS] [VOLUME]
docker volume create hello
docker run -d -p 3307:3306 -v hello:/etc/mysql/conf.d \
-v /my/own/datadir:/var/lib/mysql --restart always --name mysql01 mysql:5.7

#数据卷列表
docker volume ls

#数据卷详情
docker volume inspect hello
[
    {
        "CreatedAt": "2020-04-08T06:43:08Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/hello/_data",
        "Name": "hello",
        "Options": {},
        "Scope": "local"
    }
]
#docker cp 用于容器与主机之间的数据拷贝
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
  • SRC_PATH 指定为一个文件

    • DEST_PATH 不存在:文件名为 DEST_PATH,内容为SRC的内容
    • DEST_PATH 不存在并且以 / 结尾:报错
    • DEST_PATH 存在并且是文件:目标文件内容被替换为SRC_PATH的文件内容。
    • DEST_PATH 存在并且是目录:文件复制到目录内,文件名为SRC_PATH指定的名字
  • SRC_PATH 指定为一个目录

    • DEST_PATH 不存在:DEST_PATH创建文件夹,复制源文件夹内的所有内容

    • DEST_PATH 存在是文件:报错

    • DEST_PATH 存在是目录

      • SRC_PATH 不以 /. 结束:源文件夹复制到目标里面
      • SRC_PATH/. 结束:源文件夹里面的内容复制到目标里面

      自动创建文件夹不会做递归。把父文件夹做好

2、数据卷容器

如果需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但他专门用来提供数据卷供其他容器挂载。

docker run -it -v /idata --name idata ubuntu

docker run -it --volumes-from idata --name d01 ubuntu
docker run -it --volumes-from idata --name d02 ubuntu
#使用--volumes-from参数所挂载的数据卷容器本身不需要保持在运行状态

3、数据卷的用法细节

docker run -d -P --name nginx nginx
#方便修改nginx的配置和html页面等
#容器中 /usr/share/nginx/html
#容器中 /etc/nginx

##参照一下各种写法
# hostPath:containerPath
docker run -d -P --name nginx -v /opt/nginx/html:/usr/share/nginx/html nginx;
	#为什么看到的是403而不是index页面内容。原来容器里面变为空了?主机的内容复制到容器中,导致,容器同步到了主机的空文件夹。
	#特别是配置问津,必须提前保证我们主机挂载的目录里面提前有内容。
docker run -d -P --name nginx -v /opt/nginx:/etc/nginx nginx
	#为什么docker ps看不到;出错了。open() "/etc/nginx/nginx.conf" failed (2: No such file or directory) nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
#我就想自定义挂载路径,并且把他们挂载出来?
	# 1、复制容器的文件
		docker cp
		1、启动一个nginx,先不挂载。
		2、docker cp把运行中的nginx的内容复制出来
			Usage:	docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
					docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
		docker cp nginx:/usr/share/nginx/html /opt/hahanginx
		nginx:/usr/share/nginx/html/. 把html里面的内容复制到 /opt/hahanginx
		nginx:/usr/share/nginx/html 把html文件夹复制到 /opt/hahanginx
		
		
		完整过程
		mkdir /opt/nginx
		docker cp nginx:/usr/share/nginx/html /opt/nginx 复制html
        docker cp nginx:/etc/nginx/. /opt/nginx/conf
        docker run -d -P --name nginx -v /opt/nginx/conf:/etc/nginx -v /opt/nginx/html:/usr/share/nginx/html nginx
		
# 匿名卷方式volume,挂载任意目录
docker run -d -P --name nginx02 -v 容器路径
eg:
docker run -d -P --name nginx02 -v /usr/share/nginx/html -v /etc/nginx nginx
想要知道到底迎合到主机的哪里了?
docker inspect nginx02.
"Mounts": [
            {
                "Type": "volume",
                "Name": "9f4f8ac4c9cd9cb77df7a5386a5b68520c98ea1bb28e26b6593255c1d0ff9cdf",
                "Source": "/var/lib/docker/volumes/9f4f8ac4c9cd9cb77df7a5386a5b68520c98ea1bb28e26b6593255c1d0ff9cdf/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "68afef2bf4979e2c9369f6eb68f8a94adc61e63d3a1fb3dad7469e243442cf32",
                "Source": "/var/lib/docker/volumes/68afef2bf4979e2c9369f6eb68f8a94adc61e63d3a1fb3dad7469e243442cf32/_data",
                "Destination": "/etc/nginx",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

#匿名挂载的缺点?不好维护。 docker volume可以维护他们
docker volume ls

#具名挂载。有卷。如果有可视化界面。我们就知道卷是干嘛,就不乱删除了。
#创建好的卷,会自动的和容器中需要挂载的这个文件夹做好同步。
docker volume create 卷名字, 创建一个卷。/var/lib/docker/volumes/自定义的卷名/_data
docker run -d -P --name nginx03 -v nginxconf:/etc/nginx -v nginxhtml:/usr/share/nginx/html nginx
最佳实战。

怎么判断挂载的是卷名而不是本机目录名
  不以/开始就是卷名,以/开始就是主机名。 
 
#改变文件的读写权限
#ro:readonly rw:readwrite; 指定容器对我们这个挂载出来的内容的读写权限
docker run -d -P --name nginx04 -v nginx04conf:/etc/nginx:ro -v nginx04html:/usr/share/nginx/html:rw nginx
ro:效果
root@c721b01b2752:/etc/nginx# echo 123 > nginx.conf
bash: nginx.conf: Read-only file system
容器内不能再对ro指定的所有进行修改了。


四、Docker容器互联

1、端口映射

docker create -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name hello-mysql mysql:5.7

-p HostPort:ContainerPort | IP:HostPort:ContainerPort | HostPort:ContainerPort

  • 查看端口映射
    • docker port hello-mysql

2、容器互联

--link name:alias,name连接容器的名称,alias连接的别名

场景:我们无需暴露mysql的情况下,让web应用使用mysql;

docker run -d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d --link mysql01:mysql --name tomcat tomcat:7

docker exec -it tomcat bash
cat /etc/hosts

第一次作业

1、部署Tomcat

docker pull tomcat:jdk8-openjdk-slim

#官方 docker exec -it 
docker run -it --rm -p 8080:8080 tomcat:9.0
-it :交互模式
--rm:Automatically remove the container when it exits; 容器启动成功并且推出以后容器就自动移除;控制台ctrl-c自动删除。测试情况。dry-run.。容器就没有了

docker stop fe546673ee19 11e476bb37b6 #批量
docker ps -aq #找到所有容器的id

##默认删除的方式
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)

##一步到位的
docker rm -f $(docker ps -aq)


docker run -d -p 8080:8080 --name tomcat -v /idata/tomcat/webapp:/usr/local/tomcat/webapps tomcat:9.0
以后在/idata/tomcat/webapp里面部署项目,war

镜像:

后缀:

​ -slim:瘦身的。

alpine:更瘦的。基础系统2.5

历史?

docker的所有镜像。最基础的镜像是什么?最起码是一个系统(小linux)

centos:debain;alpine。xxx

下载镜像(tomcat.,redis),优先推荐大家用 alpine后缀的。

2、Es+Kibana

docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" \
-v /usr/share/elasticsearch/data \
-v /usr/share/elasticsearch/config \
-v /usr/share/elasticsearch/plugins \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
elasticsearch:7.6.2

# es能设置的环境变量,这里都能写。容器的名字必须唯一

docker stats 7dc #查看容器的cpu,内存,网络情况
# 必须考虑的
# 1、端口暴露问题
# 2、数据卷的挂载
# --net 

解决的问题:
1、吃内存
2、数据卷的挂载?
	es自己的所有数据都在 容器的/usr/share/elasticsearch
	容器里的结构 bin  config  data  jdk  lib  logs  modules  plugins
-v 容器里面的需要挂载的路径

#启动Kibana。kibana和es都安装在了一个一个机器
docker run -d --name kibana  -p 5601:5601 -e ELASTICSEARCH_HOSTS="http://172.16.224.124:9200" kibana:7.6.2
#kibana怎么知道es在哪里。
#es地址,千万别127.0.0.1

3、RabbitMQ

# rabbitmq:3不带管理控制台的。rabbitmq:management
docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 -v /idata/rabbitmq:/var/lib/rabbitmq rabbitmq:management

五、实战练习

1、安装MySQL

docker run -p 3306:3306 --name mysql \
-v /idata/mysql/log:/var/log/mysql \
-v /idata/mysql/data:/var/lib/mysql \
-v /idata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

docker exec -it mysql mysql -uroot -proot
#配置MySQL主从复制 
#创建master
docker run -p 3306:3306 --name mysql-master \
-v /idata/mysql/log:/var/log/mysql \
-v /idata/mysql/data:/var/lib/mysql \
-v /idata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
##配置文件
vim /idata/mysql/conf/my.cnf

[client]
default-character-set=utf8
 
[mysql]
default-character-set=utf8
 
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

server_id=1
log-bin=mysql-bin
read-only=0
binlog-do-db=icoding_test

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

#创建Slaver,和master一致,配置文件修改如下即可
server_id=2
log-bin=mysql-bin
read-only=1
binlog-do-db=icoding_test

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

#配置matser
1、添加用来同步的用户
       GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by '123456';
2、查看master状态
   show master status\G;
 
#配置slaver
1、change master to master_host='mysql-master',master_user='backup',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=0,master_port=3306;
2、start slave;
3、show slave status\G;

2、安装Redis

mkdir -p /idata/redis/conf
touch /idata/redis/conf/redis.conf

docker run -p 6379:6379 --name redis -v /idata/redis/data:/data \
-v /idata/redis/conf:/etc/redis \
-d redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

redis 自描述文件:
https://raw.githubusercontent.com/antirez/redis/4.0/redis.conf

#安装redis-cluster;3主3从方式,从为了同步备份,主进行slot数据分片
##单机情况下可以这样做。
## cluster-announce-ip 192.168.56.10 为自己服务器的ip
for port in $(seq 7001 7006); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.26.65.131 
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
appendonly yes
EOF
docker run -p ${port}:${port} -p 1${port}:1${port} --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
done
docker stop $(docker ps -a |grep redis-700 | awk '{ print $1}')
docker rm $(docker ps -a |grep redis-700 | awk '{ print $1}')

##建立集群
docker exec -it redis-7001 /bin/sh
redis-cli --cluster create 172.26.65.131:7001 172.26.65.131:7002 172.26.65.131:7003 172.26.65.131:7004 172.26.65.131:7005 172.26.65.131:7006 --cluster-replicas 1

redis-cli -c -h 192.168.56.10 -p 7006  # -c方式连接
cluster info ,cluster node;测试
#模拟网络分离的
docker network create redis --subnet 172.38.0.0/16
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done



docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \


docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf


docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker exec -it redis-1 /bin/sh
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

3、安装ElasticSearch

mkdir -p /idata/es/config
mkdir -p /idata/es/data
echo "http.host: 0.0.0.0" >> /idata/es/config/elasticsearch.yml
chmod -R 777 /idata/es/ #保证权限
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /idata/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /idata/es/data:/usr/share/elasticsearch/data \
-v /idata/es/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.0.10:9200 -p 5601:5601 \
-d kibana:7.4.2
#安装Es集群
所有之前先运行:sysctl -w vm.max_map_count=262144
我们只是测试,所以临时修改。永久修改使用下面
#防止 JVM 报错
echo vm.max_map_count=262144 >> /etc/sysctl.conf
sysctl -p

##############3-master##########################
for port in $(seq 1 3); \
do \
mkdir -p /mydata/elasticsearch/master-${port}/config
mkdir -p /mydata/elasticsearch/master-${port}/data
chmod -R 777 /mydata/elasticsearch/master-${port}
cat << EOF >/mydata/elasticsearch/master-${port}/config/elasticsearch.yml
cluster.name: my-es #集群的名称,同一个集群该值必须设置成相同的
node.name: es-master-${port} #该节点的名字
node.master: true #该节点有机会成为 master 节点
node.data: false #该节点可以存储数据
network.host: 0.0.0.0
http.host: 0.0.0.0 #所有 http 均可访问
http.port: 920${port}
transport.tcp.port: 930${port}
discovery.zen.ping_timeout: 10s #设置集群中自动发现其他节点时 ping 连接的超时时间
discovery.seed_hosts: ["172.18.12.21:9301", "172.18.12.22:9302", "172.18.12.23:9303"] #设置集群中的 Master 节点的初始列表,可以通过这些节点来自动发现其他新加入集群的节点,es7的新增配置;
cluster.initial_master_nodes: ["172.18.12.21"] #新集群初始时的候选主节点,es7 的新增配置
EOF
docker run --name elasticsearch-node-${port} \ -p 920${port}:920${port} -p 930${port}:930${port} \ --network=mynet --ip 172.18.12.2${port} \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \ -v
/mydata/elasticsearch/master-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/el
asticsearch.yml \ -v /mydata/elasticsearch/master-${port}/data:/usr/share/elasticsearch/data \ -v /mydata/elasticsearch/master-${port}/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.4.2
done




#######################3-node#######################
for port in $(seq 4 6); \
do \
mkdir -p /mydata/elasticsearch/node-${port}/config
mkdir -p /mydata/elasticsearch/node-${port}/data
chmod -R 777 /mydata/elasticsearch/node-${port}
cat << EOF >/mydata/elasticsearch/node-${port}/config/elasticsearch.yml
cluster.name: my-es #集群的名称,同一个集群该值必须设置成相同的
node.name: es-node-${port} #该节点的名字
node.master: false #该节点有机会成为 master 节点
node.data: true #该节点可以存储数据
network.host: 0.0.0.0
#network.publish_host: 192.168.56.10 #互相通信 ip,要设置为本机可被外界访问的 ip,否则
无法通信
http.host: 0.0.0.0 #所有 http 均可访问
http.port: 920${port}
transport.tcp.port: 930${port}
#discovery.zen.minimum_master_nodes: 2 #设置这个参数来保证集群中的节点可以知道其
它 N 个有 master 资格的节点。官方推荐(N/2)+1
discovery.zen.ping_timeout: 10s #设置集群中自动发现其他节点时 ping 连接的超时时间
discovery.seed_hosts: ["172.18.12.21:9301", "172.18.12.22:9302", "172.18.12.23:9303"] #设置集群中的 Master 节点的初始列表,可以通过这些节点来自动发现其他新加入集群的节点,es7
的新增配置
cluster.initial_master_nodes: ["172.18.12.21"] #新集群初始时的候选主节点,es7 的新增配置
EOF
docker run --name elasticsearch-node-${port} \ -p 920${port}:920${port} -p 930${port}:930${port} \ --network=mynet --ip 172.18.12.2${port} \ -e ES_JAVA_OPTS="-Xms300m -Xmx300m" \ -v
/mydata/elasticsearch/node-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/ela
sticsearch.yml \ -v /mydata/elasticsearch/node-${port}/data:/usr/share/elasticsearch/data \ -v /mydata/elasticsearch/node-${port}/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.4.2
done

##检查
_nodes/process?pretty 查看节点状况
_cluster/stats?pretty 查看集群状态
_cluster/health?pretty 查看集群健康状况
_cat/nodes 查看各个节点信息
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
#还可以只开放一个实例端口.其他的都用集群内访问就可以啦。
#也可以使用自定义Docker网络的方式
docker network create --driver bridge --subnet 172.21.0.0/16 --gateway 172.21.0.1 mynet
#运行容器的时候,使用 --ip --network指定网络

4、安装Nginx

  • 随便启动一个 nginx 实例, 只是为了复制出配置

    docker run -p 80:80 --name nginx -d nginx:1.10

  • 将容器内的配置文件拷贝到当前目录:

    • mkdir -p /idata/nginx/conf
    • docker container cp nginx:/etc/nginx/. /idata/nginx/conf
  • 创建新的 nginx; 执行以下命令
    docker run -p 80:80 --name nginx
    -v /idata/nginx/html:/usr/share/nginx/html
    -v /idata/nginx/logs:/var/log/nginx
    -v /idata/nginx/conf:/etc/nginx
    -d nginx:1.10

  • 给 nginx 的 html 下面放的所有资源可以直接访问;

5、安装RabbitMQ

#简单安装
docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p
25672:25672 -p 15671:15671 -p 15672:15672 -v /idata/rabbitmq:/var/lib/rabbitmq rabbitmq:management

4369, 25672 (Erlang发现&集群端口)
5672, 5671 (AMQP端口)
15672 (web管理后台端口)
61613, 61614 (STOMP协议端口)
1883, 8883 (MQTT协议端口)
https://www.rabbitmq.com/networking.html
#安装RabbitMQ镜像集群
#三台机器分别运行
mkdir -p /idata/rabbitmq
vi /idata/rabbitmq/hosts
192.168.0.48 rabbit1 rabbit1
192.168.0.47 rabbit2 rabbit2
192.168.0.46 rabbit3 rabbit3

#注意修改每个-h 参数,修改为正确的hostname
docker run -d --name rabbitmq -h rabbit1 -v /idata/rabbitmq:/var/lib/rabbitmq -v /idata/rabbitmq/hosts:/etc/hosts -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 -e RABBITMQ_ERLANG_COOKIE='icodingedu' rabbitmq:management
#上面这种方式匹配主机名适用于完全分布式情况,单机模拟集群,大家觉得还有更好的方式吗?(请使用自定义网络的方式)

#RABBITMQ_ERLANG_COOKIE 节点认证作用,部署集成时 需要同步该值

#节点加入集群
#初始化第一个节点
docker exec -it rabbitmq /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
Exit

#设置集群内的其他节点
docker exec -it rabbitmq /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbit1 #master的ip
rabbitmqctl start_app
exit

#实现镜像集群
#进入主节点进行操作
docker exec -it rabbitmq bash
rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

可以使用 rabbitmqctl list_policies -p /;查看vhost/下面的所有policy
在cluster中任意节点启用策略,策略会自动同步到集群节点
rabbitmqctl set_policy -p / ha-all "^" '{"ha-mode":"all"}'
策略模式 all 即复制到所有节点,包含新增节点,策略正则表达式为 “^” 表示所有匹配所有队列名称。“^hello”表示只匹配名为hello开始的队列

六、Docker进阶

1、Docker仓库(私有仓库)

1、阿里云

开通阿里云容器镜像服务

在这里插入图片描述

#阿里云下载镜像,需要填写前缀
docker pull registry.cn-shenzhen.aliyuncs.com/ali/mysql:[镜像版本号]

ali:命名空间
mysql:镜像仓库
  • 创建命名空间
  • 创建镜像仓库

2、Harbor

2、网络高级

#安装Es+kibana;kibana得指定es地址,
#sb-book-crud-service   mysql

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

在这里插入图片描述

​ Linux虚拟网络技术。

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

原理:

1、每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。桥接网卡

2、没启动一个容器linux主机多了一个虚拟网卡。

3、docker run -d -P --name tomcat --net bridge tomcat:8

#1、docker0网络的特点。,
	默认
	域名访问不通
	--link 域名通了,但是删了又不行
	
#2、可以让容器创建的时候使用自定义网络
	 1、自定义创建的默认default "bridge"
	 2、自定义创建一个网络网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
	所有东西实时维护好,直接域名ping同
	3、理解网络。

docker network connect [OPTIONS] NETWORK CONTAINER

跨网络连接别人就用
docker network connect mynet tomcat
效果:
	1、自定义网络,默认都可以用主机名访问通
	2、跨网络连接别人就用 docker network connect mynet tomcat

1、容器启动,指定容器ip。 docker run --ip 192.168.0.3 --net 自定义网络  
2、网络。docker network create --subnet 指定子网范围  --driver bridge 所有东西实时维护好,直接域名ping同
3、docker compose。

1、网络的创建过程

Docker创建一个容器的时候,会具体执行以下操作:

  1. 创建一对虚拟接口,分别放到本地主机和新容器的命名空间中
  2. 本地主机一段的虚拟接口连接到默认的docker0网桥或者指定网桥上,并具有一个以veth开头的唯一名字
  3. 容器一段的虚拟接口将放到新创建的容器中,并修改名字为eth0。这个接口只在容器的命名空间可见
  4. 从网桥的可用地址段中获取一个空闲的地址分配给容器的eth0(如:172.17.0.2/16),并配置默认路由网关为docker0网卡的内部接口docker0的IP地址(如:172.17.42.1/16)

完成以上,容器就可以使用它所能看到的eth0虚拟网卡来连接其他容器和访问外部网络。

2、网络模式

网络模式配置说明
bridge模式–net=bridge默认值,在Docker网桥docker0上为容器创建新的网络栈
none模式–net=none不配置网络,用户可以稍后进入容器,自行配置
container模式–net=container:name/id容器和另外一个容器共享Network namespace。
kubernetes中的pod就是多个容器共享一个Network namespace。
host模式–net=host容器和宿主机共享Network namespace
用户自定义–net=自定义网络用户自己使用network相关命令定义网络,
创建容器的时候可以指定为自己定义的网络

3、实验测试网络互连

  • 大家重点理解veth pair技术
  • –link是容器在默认网络模式下,可以互相使用容器名ping通的
  • 如果容器创建时使用自定义网络,不使用–link也是可以ping通相互的容器名
  • –link 生产一般不用,我们可以使用自定义网络的方式
  • docker network connect

4、部署一个集群(redis)


3、Dockerfile

Dockerfile指南:https://docs.docker.com/engine/reference/builder/

事情:nginx。tomcat。mysql。镜像从哪里来?

我们自己如何做一个镜像。微服务。SpringBoot。上云部署。最方便是Docker。

微服务打包成镜像。任何装了Docker。都可以下载使用。

应用–>Dockerfile—>打包成镜像—>上传到仓库(公有仓库,私有仓库)—>下载镜像—>启动运行。

移植:扩充服务器。

4、如何得到一个镜像

1、自己做的Dockefile

https://docs.docker.com/engine/reference/builder/

#nginx Dockerfile的示例
#alpine:3.11超迷你的linux 4mb;
#alpine:3.11 linux全目录 基于宿主机linux的一个统一接口。cpu,mem。主机。
FROM alpine:3.11

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"

#环境
ENV NGINX_VERSION 1.18.0
ENV NJS_VERSION   0.4.0
ENV PKG_RELEASE   1

RUN set -x \
# create nginx user/group first, to be consistent throughout docker variants
    && addgroup -g 101 -S nginx \
    && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
    && apkArch="$(cat /etc/apk/arch)" \
    && nginxPackages=" \
        nginx=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-xslt=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-geoip=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-image-filter=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-njs=${NGINX_VERSION}.${NJS_VERSION}-r${PKG_RELEASE} \
    " \
    && case "$apkArch" in \
        x86_64) \
# arches officially built by upstream
            set -x \
            && KEY_SHA512="e7fa8303923d9b95db37a77ad46c68fd4755ff935d0a534d26eba83de193c76166c68bfe7f65471bf8881004ef4aa6df3e34689c305662750c0172fca5d8552a *stdin" \
            && apk add --no-cache --virtual .cert-deps \
                openssl \
            && wget -O /tmp/nginx_signing.rsa.pub https://nginx.org/keys/nginx_signing.rsa.pub \
            && if [ "$(openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -text -noout | openssl sha512 -r)" = "$KEY_SHA512" ]; then \
                echo "key verification succeeded!"; \
                mv /tmp/nginx_signing.rsa.pub /etc/apk/keys/; \
            else \
                echo "key verification failed!"; \
                exit 1; \
            fi \
            && apk del .cert-deps \
            && apk add -X "https://nginx.org/packages/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \
            ;; \
        *) \
# we're on an architecture upstream doesn't officially build for
# let's build binaries from the published packaging sources
            set -x \
            && tempDir="$(mktemp -d)" \
            && chown nobody:nobody $tempDir \
            && apk add --no-cache --virtual .build-deps \
                gcc \
                libc-dev \
                make \
                openssl-dev \
                pcre-dev \
                zlib-dev \
                linux-headers \
                libxslt-dev \
                gd-dev \
                geoip-dev \
                perl-dev \
                libedit-dev \
                mercurial \
                bash \
                alpine-sdk \
                findutils \
            && su nobody -s /bin/sh -c " \
                export HOME=${tempDir} \
                && cd ${tempDir} \
                && hg clone https://hg.nginx.org/pkg-oss \
                && cd pkg-oss \
                && hg up -r 474 \
                && cd alpine \
                && make all \
                && apk index -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \
                && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \
                " \
            && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \
            && apk del .build-deps \
            && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \
            ;; \
    esac \
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
    && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \
    && if [ -n "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi \
    && if [ -n "/etc/apk/keys/nginx_signing.rsa.pub" ]; then rm -f /etc/apk/keys/nginx_signing.rsa.pub; fi \
# Bring in gettext so we can get `envsubst`, then throw
# the rest away. To do this, we need to install `gettext`
# then move `envsubst` out of the way so `gettext` can
# be deleted completely, then move `envsubst` back.
    && apk add --no-cache --virtual .gettext gettext \
    && mv /usr/bin/envsubst /tmp/ \
    \
    && runDeps="$( \
        scanelf --needed --nobanner /tmp/envsubst \
            | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
            | sort -u \
            | xargs -r apk info --installed \
            | sort -u \
    )" \
    && apk add --no-cache $runDeps \
    && apk del .gettext \
    && mv /tmp/envsubst /usr/local/bin/ \
# Bring in tzdata so users could set the timezones through the environment
# variables
    && apk add --no-cache tzdata \
# Bring in curl and ca-certificates to make registering on DNS SD easier
    && apk add --no-cache curl ca-certificates \
# forward request and error logs to docker log collector
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log \
# make default server listen on ipv6
    && sed -i -E 's,listen       80;,listen       80;\n    listen  [::]:80;,' \
        /etc/nginx/conf.d/default.conf

EXPOSE 80

STOPSIGNAL SIGTERM

CMD ["nginx", "-g", "daemon off;"]
# Dockerfile复原了我们在linux上安装nginx的过程。

2、别人给我们准备好的文件。xxx.tar。可以通过硬盘传输使用。

在这里插入图片描述

1、创建项目dockerfile

2、上传项目到服务器。

3、进入项目,构建镜像到本地仓库;

  • docker build -t nginx:1.0 -f ./Dockerfile . 别忘了最后的小数点。
  • docker images 查看镜像
  • docker exec -it 容器id /bin/bash;进入容器,修改容器
  • docker commit -a “icoding” -m “nginxxx” 容器id mynginx:2.0
    • docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    • OPTIONS说明:
      • -a :提交的镜像作者;
      • -c :使用Dockerfile指令来创建镜像;
      • -m :提交时的说明文字;
      • -p :在commit时,将容器暂停。
  • docker login : 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
  • docker login -u 用户名 -p 密码
  • docker logout : 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub

4、推送镜像到docker hub

  • 标记镜像,docker tag local-image:tagname username/new-repo:tagname
  • 上传镜像,docker push username/new-repo:tagname

5、保存镜像,加载镜像

  • 可以保存镜像为tar,使用u盘等设备复制到任意docker主机,再次加载镜像
  • 保存:docker save spring-boot-docker -o /home/spring-boot-docker.tar
  • 加载:docker load -i spring-boot-docker.tar

6、阿里云操作

  • 登录阿里云,密码就是开通镜像仓库时 的密码
    • docker login --username=icoding registry.cn-hangzhou.aliyuncs.com
  • 拉取镜像
    • docker pull registry.cn-hangzhou.aliyuncs.com/icoding/i-nginx:v1.0
  • 推送镜像
    • docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/icoding/icoding-nginx:v2
    • docker push registry.cn-hangzhou.aliyuncs.com/icoding/icoding-nginx:v2

2、Dockerfile详解

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。

一般而言,Dockerfile可以分为四部分

基础镜像信息 维护者信息 镜像操作指令 启动时执行指令

指令说明
FROM指定基础镜像
MAINTAINER指定维护者信息,已经过时,可以使用LABEL maintainer=xxx 来替代
RUN运行命令 v
CMD指定启动容器时默认的命令 v
LABEL指定生成镜像的元数据标签信息 v
EXPOSE声明镜像内服务监听的端口 v
ENV指定环境变量,可以在docker run的时候使用-e改变 v
ADD复制指定的src路径下的内容到容器中的dest路径下,src可以为url会自动下载,可以为tar文件,会自动解压
COPY复制本地主机的src路径下的内容到镜像中的dest路径下,但不会自动解压等
ENTRYPOINT指定镜像的默认入口.运行命令 v
VOLUME创建数据卷挂载点
USER指定运行容器时的用户名或UID
WORKDIR配置工作目录,为后续的RUN、CMD、ENTRYPOINT指令配置工作目录
ARG指定镜像内使用的参数(如版本号信息等),可以在build的时候,使用–build-args改变 v
OBBUILD配置当创建的镜像作为其他镜像的基础镜像是,所指定的创建操作指令
STOPSIGNAL容器退出的信号值
HEALTHCHECK健康检查
SHELL指定使用shell时的默认shell类型

1、RUN、CMD、ENTRYPOINT区别

  1. RUN 执行命令并创建新的镜像层RUN 经常用于安装软件包(在构建镜像时运行的)。
  2. CMD 设置容器启动后默认执行的命令及其参数但 CMD 能够被 docker run 后面跟的命令行参数替换。
  3. ENTRYPOINT 配置容器启动时运行的命令。
  4. 以上命令都可以使用shell或者exec方式执行
  5. CMD ["executable","param1","param2"] (exec form, this is the preferred form)
  6. CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
  7. CMD command param1 param2 (shell form)

2、shell和exec方式

  1. shell 是 /bin/sh -c 的方式,

  2. exec [“/bin/sh”,“-c”,command] 的方式== shell方式

eg:shell方式

ENV name icoding  
ENTRYPOINT echo "Hello, $name" 
#输出 Hello icoding

ENTRYPOINT ["/bin/echo", "Hello, $name"]
#输出 Hello $name

ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
#输出 Hello icoding

##建议:CMD 和 ENTRYPOINT 推荐使用 Exec 格式因为指令可读性更强更容易理解。RUN 则两种格式都可以。exec的时候要获取环境变量等值,就用/bin/sh -c 即可。
No ENTRYPOINTENTRYPOINT exec_entry p1_entryENTRYPOINT [“exec_entry”, “p1_entry”]
No CMDerror, not allowed/bin/sh -c exec_entry p1_entryexec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”]p1_cmd p2_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd/bin/sh -c exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

3、实战Dockerfile

#1、ping命令小工具。
编写Dockerfile-->打包镜像--->根据这个镜像启动容器使用容器的功能
docker build -t hello .
-t:tag标签。镜像名字
.:在当前目录下工作
默认.这个目录下就得有一个 Dockerfile
FROM alpine
CMD ping baidu.com

#2、文件名不是Dockerfile。用-f 指定
docker build -f Dockerfile2 -t hello:v1.0 .
docker run -d --name hello hello;

#3、默认构建出来的镜像,放到了我们的本地镜像仓库。
	1)、登陆到dockerhub
	2)、dockehub国外,就算能Push,非常慢。阿里云加速的是下载。
	
#4、把这个镜像发布到Docker hub
	1)、docker login -u icodingallen;登陆到docker hub
	2)、docker push nginx:v1.0;推送过去。
	太慢了
#5、搭建私有的镜像仓库。使用阿里云的镜像仓库(免费)。
	1)、docker login --username=lyt_goodtogread@163.com registry.cn-hangzhou.aliyuncs.com

为了团队自治。只能看到自己的仓库的所有镜像。namespace;
创建镜像仓库。保存镜像各种版本,book: 1 2 3 4 5
docker tag hello:v1.0 registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.3
docker push registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.3

在这里插入图片描述

在这里插入图片描述

docker.io/libarary/hello:latest

registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.0

镜像—》打包–》上传。

5、Dockerfile区分一些易混淆的指令

1、USER 执行cmd等之类命令的使用那个用户
alpine  sudo   gosu
FROM centos
RUN groupadd -r abc && useradd -r -g abc aaa
USER aaa
CMD whoami
# CMD 就是容器启动以后要执行的命令
2、ARG、ENV
  • The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build :arg在构建期间。docker build
  • The environment variables set using ENV will persist when a container is run from the resulting image. You can view the values using docker inspect, and change them using docker run --env =. env在运行是可以用到的
FROM alpine

ARG bbb haha
ENV abc 666

CMD echo $bbb
容器运行的时候arg的东西拿不到

CMD echo $abc
容器运行的时候env的能拿到


FROM alpine

ARG bbb haha
ENV abc=$bbb

CMD echo $abc

ARG指定的值,在镜像构建的后面位置,构建期间都可以使用到。

改变这些值行不行
docker build -f Dockerfile-arg-env -t file-arg --build-arg bbb=888 --build-arg abc=777 .
结果888 


# 构建时 bbb=888 abc=777 ,cmd打印888.原因 构建时不能改变env
# 运行时 
\ARGENV
build时√。–build-arg改变 构建参数(ARG声明)生效,能不能改(不能)
运行时不生效生效。能改 -e abc

最佳实战:

ARG:定义一些版本信息

​ FROM alpine

​ ARG version=1

​ RUN yum install nginx:$version

Env:运行时的环境变量。

ENV env = --spring.profile.active=prod

​ -e修改。sb java -jar xxx.jar $env

3、ADD和COPY
#构建了一个SpringBoot镜像。 xxx.jar 
/opt

docker build -t hello .

ADD:将当前目录下的内容放到镜像里面一起打包。

COPY:将当前目录下的内容放到镜像里面一起打包。

ADD ["<src1>","<src2>","<dest>"]  dest:容器里面的目录
可以指定很多种路径地址。自动下载,解压复制。
FROM alpine

ADD hello.tar /opt/hello

COPY hello.tar /opt/world/

CMD echo "1234"

这个东西构建的镜像为什么docker run -d 不行。因为容器运行的是ech 1234;
没有一个守护进程一直运行。
CMD ping baidu.com


4、VOLUME和WORKDIR
VOLUME:指定容器需要挂载的卷
WORKDIR:工作目录。
	1、以后的其他命令在这个目录里面运行
	2、exec进去都默认来到了 WORKDIR 指定的目录。sh
	docker run -it --rm file-volume sh
	
WORKDIR


WORKDIR /root  == RUN cd /root

挂载麻烦。自动挂载。
FROM alpine

WORKDIR /opt/a

VOLUME /opt/b

COPY hello.txt .

ADD hello.tar /opt/b

CMD whoami

volume声明的挂载目录,即使容器运行的时候,不用-v进行挂载。docker也会自动的进行匿名挂载。
nginx:
5、RUN、CMD、ENTRYPOINT

相同点:运行命令

不同点:

​ RUN:在构建镜像的时候运行的命令

CMD、ENTRYPOINT:在容器启动运行的命令

测试RUN;

#想构建一个具有git功能的镜像。
FROM centos

RUN yum install -y git

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
CMD echo "git clone success"
#CMD 容器运行的时候CMD的命令才执行。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相同的镜像layer层发生变化,只有这层变化。

  • -RUN指令的所有命令都在镜像docker build期间就执行
  • CMD和ENTRYPOINT在容器启动时运行
    • CMD 容器运行的时候CMD的命令才执行。docker run -it --rm file-run bash 能进容器中
    • 替换为ENTRYPOINT。虽然指令运行了。但是 docker run -it --rm file-run bash 。最后的bash没有进去,失效了。

无论是CMD还是ENTRYPOINT还是RUN

  • RUN (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows) RUN yum install -y git;/bin/sh -c可以动态获取一些变量
  • RUN ["executable", "param1", "param2"] (exec form);无法动态获取一些变量
FROM centos

ARG soft=git
RUN ["yum install","-y","$soft"] #这是错误的。因为非`/bin/sh -c`方式,用不到前面声明的ARG,ENV

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
ENTRYPOINT echo "git clone success"

在这里插入图片描述

# bash-c 和 数组方式的区别,  修改后的;安装正确。
FROM centos

ARG soft=git
RUN ["/bin/sh","-c","yum install -y $soft"]
#-c command:后免是完整命令
WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
ENTRYPOINT echo "git clone success"

RUN、CMD、ENTRYPOINT都支持一下两种方式

The exec form, which is the preferred form:

ENTRYPOINT ["executable", "param1", "param2"]

The shell form:

ENTRYPOINT command param1 param2

总结:

  • 如果运行命令是。[]方式,默认不是bash -c就无法用变化,普通的方式RUN yum -install -y $soft可以使用变量。

  • CMD、ENTRYPOINT的最佳实战

    • Dockerfile文件必须至少有一个 CMD 或者ENTRYPOINT 命令.
    • ENTRYPOINT 用来定义容器如何运行.
    • CMD 应该被用来作为给ENTRYPOINT 传递。默认参数的一种方式
    • CMD 将会被覆盖,容器运行时指定参数的时候. ENTRYPOINT 命令不会被覆盖。
    • CMD多个只会有一个生效。
    • ENTRYPOINT :不被传入的指令覆盖,但是多个也只有一个生效。

    为什么我的指令Dockerfile写CMD的时候,docker run -it --rm file-run bash可以进控制台,而ENTRYPOINT 不行?

    运行效果:

    • Dockerfile是CMD;没打印git clone success。但是bash生效。

在这里插入图片描述

  • Dockerfile 是 ENTRYPOINT;打印了git clone success但是没有进容器(bash没生效)

在这里插入图片描述

  • 混写。CMD + ENTRYPOINT
FROM centos

ARG soft=git
RUN ["/bin/bash","-c","yum install -y $soft"]

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data


CMD ["nginx"] #CMD给entrypoint提供参数
ENTRYPOINT ["yum","install","-y"]


运行:
docker run -it --rm file-run maven
FROM centos

ARG soft=git
RUN ["/bin/bash","-c","yum install -y $soft"]

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data


CMD ["","","",""] #可以放空
ENTRYPOINT ["/bin/sh","-c","yum install -y"]

#容器启动就是yum install -y "";自己启动命令加上git
CMD 后面有N参数。传了参数替换N个还是最后一个?
docker run -it --rm file-run maven  CMD ["maven"]docker run -it --rm file-run maven  CMD [“”,“”,"maven"]

目的:构建镜像。SpringBoot编写的微服务,怎么做镜像?

1、运行的业务的目标环境?SB服务。java环境。FROM

2、怎么启动业务的。得到jar包,java -jar xxx.jar --spring.profile.active=prod --server.port=8080;决定镜像的ENTRYPOINT怎么写。docker exec?docker run(第一次容器启动要执行)?

docker exec haha -it bash【和entrypoint,cmd没啥关系】;

3、业务运行的时候需要啥?java。jar。jar包就想办法放进镜像中。COPY 。ADD

4、业务的那些数据是需要做持久化。VOLUME怎么写。

FROM java:8


#服务器只有dockerfile和jar在一起
COPY *.jar /app.jar

#即使运行没有-v,也会匿名挂载
VOLUME ["/logs"]

CMD ["--server.port=8080"]

EXPOSE ["8080"]

ENTRYPOINT ["java","-jar","/app.jar"]

4、idea快速整合使用

作为一个了解。

1、 Docker开启远程访问
#修改该Docker服务文件
vi /lib/systemd/system/docker.service
#修改ExecStart这行,将原来注释,加上这个命令
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
#重新加载配置文件
systemctl daemon-reload
#重启服务
systemctl restart docker.service
#查看端口是否开启
netstat -nlpt #如果找不到netstat命令,可进行安装。yum install net-tools
#直接curl看是否生效
curl http://127.0.0.1:2375/info
2、IDEA安装Docker插件

在这里插入图片描述

3、IDEA配置docker

在这里插入图片描述

4、也可以整合自己的私有镜像仓库

在这里插入图片描述

可以提供非常方便的部署功能

在这里插入图片描述

docker build -t hello-java . && docker run -p 88:8080 -v /logs:/logs --name hello-666 hello-java

Dockerfile解耦应用的开发与部署。

maven插件再把部署流程一配置就不解耦。,

应用。代码变了改应用。部署只改Dockerfile。

maven。代码部署放在了一个完整的生命周期。运维人员想要改网络部署等配置,还得改pom。CICD只需要一个Dockerfile。

5、docker-maven-plugin

市面上docker-maven-plugin太多,我们推荐一个 docker-maven-plugin,照着文档使用就行。不管使用哪一种docker插件来构造image,都比不上直接用Dockerfile编写简单,而且可复用,不用学习不同插件不同的构造规则。

最好给自己的Docker服务器配置阿里云镜像加速,否则经常导致镜像下载不来的情况

fabric8io的有两大功能:

  1. 构造并推送Docker镜像
  2. 启动和停止Docker容器
<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.33.0</version>

    <!--全局配置-->
    <configuration>
        <!--这一部分是为了实现对远程docker容器的控制-->
        <!--docker主机地址,用于完成docker各项功能,注意是tcp不是http!-->
        <dockerHost>tcp://公网IP:2376</dockerHost>
        <!--docker远程访问所需证书地址,如果docker远程主机没有启用TLS验证则不需要配证书-->
        <certPath>${project.basedir}/docker/ssh</certPath>

        <!--这一部分是为了实现docker镜像的构建和推送-->
        <!--registry地址,用于推送,拉取镜像,我这里用的是阿里的registry-->
        <registry>registry.cn-shenzhen.aliyuncs.com</registry>
        <!--认证配置,用于私有registry认证,如果忘记了可以去阿里的registry查看-->
        <authConfig>
            <push>
                <username>这里填registry的用户名</username>
                <password>这里填registry的密码</password>
            </push>
        </authConfig>

        <!--镜像相关配置,支持多镜像-->
        <images>
            <!-- 单个镜像配置 -->
            <image>
                <!--镜像名(含版本号)-->
                <name>命名空间/仓库名称:镜像版本号</name>
                <!--别名:用于容器命名和在docker-compose.yml文件只能找到对应名字的配置-->
                <alias>${project.name}</alias>
                <!--镜像build相关配置-->
                <build>
                    <!--使用dockerFile文件-->
                    <dockerFile>${project.basedir}/docker/${project.name}</dockerFile>
                </build>
                <!--配置docker-compose文件-->
                <external>
                    <type>compose</type>
                    <basedir>${project.basedir}/docker</basedir>
                    <composeFile>docker-compose.yml</composeFile>
                </external>
                <!--容器run相关配置-->
                <run>
                    <!--配置运行时容器命名策略为:别名,如果不指定则默认为none,即使用随机分配名称-->
                    <namingStrategy>alias</namingStrategy>
                </run>
            </image>
        </images>
    </configuration>
</plugin>
maven指令功能
docker:start创建和启动容器
docker:stop停止并销毁容器
docker:build构建镜像
docker:watch自动进行重建和重启
docker:push将镜像推送到registry
docker:remove从本地docker主机删除镜像
docker:logs显示容器日志
docker:source将docker build archive附加到Maven项目
docker:save将镜像保存到文件
docker:volume-create创建卷以在容器之间共享数据
docker:volume-remove删除创建的卷
#打包到容器运行的完整流程
mvn clean package docker:stop docker:remove docker:build docker:run 
#不是每一次运行都要推送镜像,如果要的话可以单独调用docker:push
mvn docker:push
#示例配置
<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.33.0</version>

    <configuration>
        <dockerHost>tcp://111.229.61.54:2375</dockerHost>
        <registry>registry.cn-shenzhen.aliyuncs.com</registry>
        <authConfig>
            <push>
                <username>icodingallen</username>
                <password>icoding123</password>
            </push>
        </authConfig>
        <images>
            <image>
                <name>icoding/icoding-docker:v1.2</name>
                <build>
<!--使用dockerFile文件 <dockerFile>${project.basedir}/docker/${project.name}</dockerFile>-->
                    <dockerFile>${project.basedir}/Dockerfile</dockerFile>
                </build>
                <run>
                    <ports>
                        <port>8080:8080</port>
                    </ports>
                </run>
            </image>
        </images>
    </configuration>
</plugin>
FROM java:8
LABEL maintainer=icoding
ADD target/*.jar /app.jar
EXPOSE 8080
CMD ["java","-jar","app.jar"]
@RestController
public class HelloController {

    @Value("${project.version}")
    String ver;
    @Value("${project.name}")
    String name;

    @GetMapping("/")
    public String hello(){
        return "Hello Docker!"+ver+"=>"+name;
    }
}
#获取maven pom对象的相关属性值。在springboot中获取如下
project.version=@project.version@
project.name=@project.name@
#在pom文件中直接使用${project.xxxx},按照对象属性关系获取即可

七、Docker Compose

https://docs.docker.com/compose/

前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知

使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  3. Run docker-compose up and Compose starts and runs your entire app.

1、安装

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

docker-compose version

2、体验

1、创建一个测试应用

#1、Create a directory for the project:

mkdir composetest
cd composetest

#2、Create a file called app.py in your project directory and paste this in:
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)
#3、Create another file called requirements.txt in your project directory and paste this in:
flask
redis

2、创建Dockerfile

#In your project directory, create a file named Dockerfile and paste the following:
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
COPY . .
CMD ["flask", "run"]

3、在Compose file里定义服务

#Create a file called docker-compose.yml in your project directory and paste the following:
version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

4、Compose构建和运行应用

docker-compose up -d
#访问 http://localhost:5000/ 测试效果

详情:https://docs.docker.com/compose/compose-file/#reference-and-guidelines

5、概念

工程、服务、容器

  • Docker Compose 将所管理的容器分为三层,分别是工程(project)、服务(service)、容器(container)
  • Docker Compose 运行目录下的所有文件(docker-compose.yml)组成一个工程,一个工程包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖,一个服务可包括多个容器实例

6、实战-使用Compose构建一个wordpress应用

https://docs.docker.com/compose/wordpress/

八、Docker Swarm

https://docs.docker.com/swarm/overview/

1、架构

在这里插入图片描述

2、进阶

1、Swarm集群(2manager-3worker)

https://docs.docker.com/engine/swarm/ swarm入门操作

In Docker 1.12 and higher;Swarm已经内置了,无需安装

在所有docker主机上,选定一个主节点。运行docker swarm init --advertise-addr ip地址,初始化一个manager

docker swarm init \
--advertise-addr 192.168.121.142
--listen-addr 192.168.121.142
#关于advertise-addr和listen-addr这两个参数,前者用来指定其他节点连接m0时的地址,后者指定承载swarm流量的IP和端口

在这里插入图片描述

剩下节点使用docker swarm join即可;

在主节点

docker swarm join-token manager
#可以生成Manager节点的join信息,再选中一个节点,运行命令就可以作为manager加入

docker node ls #查看节点信息

2、基本概念

1.Swarm
集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm
2.Node
一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。
要将应用程序部署到swarm,请将服务定义提交给 管理器节点。管理器节点将称为任务的工作单元分派 给工作节点。
Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。
工作节点接收并执行从管理器节点分派的任务。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。
3.Service
一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,你需要指定要使用的容器镜像。
4.Task
任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点
------------------------------------------使用方法-------------------------------------
docker swarm:集群管理,子命令有init, ``join``, leave, update。(docker swarm --help查看帮助)
docker service:服务创建,子命令有create, inspect, update, remove, tasks。(docker service--help查看帮助)
docker node:节点管理,子命令有accept, promote, demote, inspect, update, tasks, ``ls``, ``rm``。(docker node --help查看帮助)

在这里插入图片描述

3、Swarm的工作模式

1. Node

在这里插入图片描述

2.Service

在这里插入图片描述

3.任务与调度

在这里插入图片描述

4.服务副本与全局服务

在这里插入图片描述

3、测试

在Swarm中部署服务(nginx为例)

#1、可以创建网络
# docker network create -d overlay nginx_net
#2、部署service
docker service create --replicas 1 --name my_nginx -p 88:80 nginx    
# 就创建了一个具有一个副本(--replicas 1 )的nginx服务,使用镜像nginx
docker service ls
docker service inspect --pretty my_nginx
docker service ps my_nginx
#3、扩容
docker service scale my_nginx=4
docker service ps my_nginx
#4、模拟宕机查看效果
systemctl stop docker
docker node ls
docker service ps my_nginx
#5、Swarm 动态缩容服务(scale)
docker service scale my_nginx=1
#6、update扩缩容
docker service update --replicas 3 my_nginx
#7、update镜像升级
docker service update --image nginx:latest my_nginx
#8、服务移除
docker service rm my_nginx
#1、创建名为tomcat-net的覆盖网络(Overlay Netowork),这是个二层网络,处于该网络下的docker容器,即使宿主机不一样,也能相互访问:
docker network create -d overlay tomcat-net
#2、创建名为tomcat的服务,使用了刚才创建的覆盖网络:
docker service create --name tomcat \
--network tomcat-net \
-p 8080:8080 \
--replicas 2 \
tomcat:7.0.96-jdk8-openjdk
#3、执行命令docker service ls查看当前所有服务:
#4、执行命令docker service ps tomcat查看名为tomcat的服务,可见三个容器分别部署在m0、m2、w1机器上:
#5、执行命令docker service inspect --pretty tomcat查看名为tomcat的服务的详细信息(去掉--pretty可以看到更完整的):
#6、访问三个节点的tomcat,都能访问
#7、扩缩容
docker service scale tomcat=5
#8、滚动更新
docker service update \
--image tomcat:9.0.24-jdk11-openjdk \
--update-parallelism 1 \
--update-delay 10s tomcat
#update-parallelism:每次更新的容器数量,这里设置为1,表示每一个容器升级成功后才去升级下一个;
#update-delay:每一批升级成功后,升级下一批之前的等待时间,这里表示升级一个容器后等10秒再升级下一个;
#在升级过程中执行命令docker service ps tomcat查看服务,可以看到新版本容器逐个启动的过程:
#9、移除服务
docker service rm tomcat

服务模式

  • 服务模式一共有两种:Ingress和Host,如果不指定,则默认的是Ingress;
    • Ingress模式下,到达Swarm任何节点的8080端口的流量,都会映射到任何服务副本的内部80端口,就算该节点上没有tomcat服务副本也会映射;
    • Host模式下,仅在运行有容器副本的机器上开放端口,使用Host模式的命令如下:
docker service create --name tomcat \
--network tomcat-net \
--publish published=8080,target=8080,mode=host \
--replicas 3 \
tomcat:7.0.96-jdk8-openjdk

4、Docker Stack和Docker Compose区别

  • Docker stack会忽略了“构建”指令,无法使用stack命令构建新镜像,它是需要镜像是预先已经构建好的。 所以docker-compose更适合于开发场景;
  • Docker Compose是一个Python项目,在内部,它使用Docker API规范来操作容器。所以需要安装Docker -compose,以便与Docker一起在您的计算机上使用;
  • Docker Stack功能包含在Docker引擎中。你不需要安装额外的包来使用它,docker stacks 只是swarm mode的一部分。
  • Docker stack不支持基于第2版写的docker-compose.yml ,也就是version版本至少为3。然而Docker Compose对版本为2和3的 文件仍然可以处理;
  • docker stack把docker compose的所有工作都做完了,因此docker stack将占主导地位。同时,对于大多数用户来说,切换到使用docker stack既不困难,也不需要太多的开销。如果您是Docker新手,或正在选择用于新项目的技术,请使用docker stack。

5、Docker Stack常用命令

命令描述
docker stack deploy部署新的堆栈或更新现有堆栈
docker stack ls列出现有堆栈
docker stack ps列出堆栈中的任务
docker stack rm删除一个或多个堆栈
docker stack services列出堆栈中的服务

​ 推荐实验: https://blog.csdn.net/huangjun0210/article/details/86502021

6、swarm网络细节

在 Swarm Service 中有三个重要的网络概念:

  • Overlay networks 管理 Swarm 中 Docker 守护进程间的通信。你可以将服务附加到一个或多个已存在的 overlay 网络上,使得服务与服务之间能够通信。
  • ingress network 是一个特殊的 overlay 网络,用于服务节点间的负载均衡。当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为 IPVS 的模块。IPVS 跟踪参与该服务的所有IP地址,选择其中的一个,并通过 ingress 网络将请求路由到它。
    初始化或加入 Swarm 集群时会自动创建 ingress 网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本允许你自定义。
  • docker_gwbridge是一种桥接网络,将 overlay 网络(包括 ingress 网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的 docker_gwbridge 网络。
    docker_gwbridge 网络在初始化或加入 Swarm 时自动创建。大多数情况下,用户不需要自定义配置,但是 Docker 允许自定义。
名称类型注释
docker_gwbridgebridgenone
ingressoverlaynone
custom-networkoverlaynone
  • docker_gwbridge和ingress是swarm自动创建的,当用户执行了docker swarm init/connect之后。

  • docker_gwbridge是bridge类型的负责本机container和主机直接的连接

  • ingress负责service在多个主机container之间的路由。

  • custom-network是用户自己创建的overlay网络,通常我们都需要创建自己的network并把service挂在上面。

在这里插入图片描述

https://docs.docker.com/engine/swarm/ingress/

docker service create --name tomcat \
--network tomcat-net \
--publish published=8080,target=8080,mode=host \
--replicas 3 \
tomcat:7.0.96-jdk8-openjdk

4、Docker Stack和Docker Compose区别

  • Docker stack会忽略了“构建”指令,无法使用stack命令构建新镜像,它是需要镜像是预先已经构建好的。 所以docker-compose更适合于开发场景;
  • Docker Compose是一个Python项目,在内部,它使用Docker API规范来操作容器。所以需要安装Docker -compose,以便与Docker一起在您的计算机上使用;
  • Docker Stack功能包含在Docker引擎中。你不需要安装额外的包来使用它,docker stacks 只是swarm mode的一部分。
  • Docker stack不支持基于第2版写的docker-compose.yml ,也就是version版本至少为3。然而Docker Compose对版本为2和3的 文件仍然可以处理;
  • docker stack把docker compose的所有工作都做完了,因此docker stack将占主导地位。同时,对于大多数用户来说,切换到使用docker stack既不困难,也不需要太多的开销。如果您是Docker新手,或正在选择用于新项目的技术,请使用docker stack。

5、Docker Stack常用命令

命令描述
docker stack deploy部署新的堆栈或更新现有堆栈
docker stack ls列出现有堆栈
docker stack ps列出堆栈中的任务
docker stack rm删除一个或多个堆栈
docker stack services列出堆栈中的服务

​ 推荐实验: https://blog.csdn.net/huangjun0210/article/details/86502021

6、swarm网络细节

在 Swarm Service 中有三个重要的网络概念:

  • Overlay networks 管理 Swarm 中 Docker 守护进程间的通信。你可以将服务附加到一个或多个已存在的 overlay 网络上,使得服务与服务之间能够通信。
  • ingress network 是一个特殊的 overlay 网络,用于服务节点间的负载均衡。当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为 IPVS 的模块。IPVS 跟踪参与该服务的所有IP地址,选择其中的一个,并通过 ingress 网络将请求路由到它。
    初始化或加入 Swarm 集群时会自动创建 ingress 网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本允许你自定义。
  • docker_gwbridge是一种桥接网络,将 overlay 网络(包括 ingress 网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的 docker_gwbridge 网络。
    docker_gwbridge 网络在初始化或加入 Swarm 时自动创建。大多数情况下,用户不需要自定义配置,但是 Docker 允许自定义。
名称类型注释
docker_gwbridgebridgenone
ingressoverlaynone
custom-networkoverlaynone
  • docker_gwbridge和ingress是swarm自动创建的,当用户执行了docker swarm init/connect之后。

  • docker_gwbridge是bridge类型的负责本机container和主机直接的连接

  • ingress负责service在多个主机container之间的路由。

  • custom-network是用户自己创建的overlay网络,通常我们都需要创建自己的network并把service挂在上面。

https://docs.docker.com/engine/swarm/ingress/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值