一、概述
1.Docker 与传统虚拟机对比
Docker 和传统虚拟机都属于虚拟化技术,但是两者有较大的差异。主要体现在:
- 虚拟化层次
传统虚拟机是完全虚拟化,需要模拟整个硬件设备,运行完整的操作系统。而Docker是应用容器虚拟化,只需要虚拟出一个能独立运行应用的空间。 - 资源占用
传统虚拟机需要运行完整的操作系统,资源占用较大。而Docker直接运行在宿主机的内核上,只需要占用很少的系统资源。 - 启动速度
传统虚拟机启动较慢,需要引导整个操作系统。而Docker镜像更轻量,启动很快。 - 存储需求
传统虚拟机磁盘镜像较大,通常几十GB。而Docker镜像通常只有几MB,极轻量。 - 隔离性
传统虚拟机具有较高的隔离性,具有自己的内核和根文件系统。而Docker仅隔离应用进程和文件系统,共享内核和其他资源。
所以总体来说:
- 传统虚拟机提供的是硬件虚拟化,完全模拟一套硬件来运行操作系统和应用。资源占用高,启动慢,适用于隔离度高的场景。
- Docker提供的是应用容器虚拟化,直接在宿主机运行应用程序,无需模拟硬件和运行完整操作系统。资源占用小,启动快,适用于高密度部署应用场景。
Docker相对于传统虚拟机有较大优势,但是安全性稍差。所以两者各有利弊,应根据实际需求选择使用。
2.Docker工作原理
Dcoker三要素
- 镜像
- 容器
- 仓库
二、安装
Docker的实质是在已经运行的Linux环境下创建一个隔离的文件环境,因此Docker必须部署在Linux内核的系统上,如果是其它环境就必须安装一个虚拟的Linux环境。
以CentOS为例。
1.系统要求
CentOS7及以上版本。
//查看linux内核 centOs7及以上
cat /etc/redhat-release
2.安装与操作
2.1 官网安装地址
https://docs.docker.com/engine/install/centos
2.2 安装
按照官网的步骤进行安装即可。
注意:镜像库使用国内镜像,不建议使用官网提供的地址。
安装gcc
//gcc -v。查看是否已安装gcc。如果没有请安装
yum -y install gcc
yum -y install gcc-c++
安装docker引擎库
//安装yum-utils
yum install -y yum-utils
//配置镜像仓库。注意:镜像仓库要配置国内的,如果是国外(官网)的会特别慢
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
//更新yum软件包索引。相当重建yum包索引,会加快包安装速度。非必须。
yum makecache fast
//可以查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r
//安装docker-ce
yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
//或安装指定版本
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
卸载
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
操作
//启动
systemctl start docker
//版本
docker version
//运行
docker run hello-world
3.镜像加速器(阿里云)
国内的镜像加速器有很多种,如:阿里云、网易云、华为云等,我们以阿里云为例。
根据阿里云提供的方式,将镜像加速器地址配置到docker中。可提高镜像的发布、拉取和容器编排的效率。
按照阿里云提供的方式配置完后运行命令 docker run hello-world,如果能成功打印出 hello from docker!表示配置成功。
三、常用命令
1.帮助启动类命令
//启动
systemctl start docker
//停止
systemctl stop docker
//重启
systemctl restart docker
//设置docker开机自启动
systemctl enable docker
//查看docker运行状态(显示绿色代表正常启动)
systemctl status docker
//查看docker概要信息
docker info
//查看docker总体帮助文档
docker --help
//查看docker命令帮助文档
docker 具体命令 --help
2.镜像命令
//列出本机上的镜像
docker images
-a 列出本地所以镜像,包含历史版本
-q 只显示镜像id
//镜像库中查找镜像
docker search 镜像名字
--limit 只列出n个镜像,默认25个。如:docker search --limit 5 redis(查找star最高的5个镜像)
//拉取镜像
docker pull 镜像名字[:TAG]
//查看镜像/容器/数据卷所占的空间(就是查看所有镜像的家底)
docker system df
//镜像删除
docker rmi 镜像名字/ID
//镜像暴力删除(可能被别的容器引用)
docker rmi -f 镜像名字/ID
//镜像暴力删除多个
docker rmi -f 镜像名字1:tags 镜像名字2:tags
//镜像全部删除
docker rmi -f ${docker images -qa}
3.容器命令
新建 + 启动容器
//使用镜像ubuntu以交互模式 启动一个容器,并在容器内执行/bin/bash命令
docker run -it --name=myu1 ubuntu /bin/bash
-i 交互式操作,通常与-t一起使用
-t 终端,通常与-i一起使用
--name 给容器指定一个名字
-d 后台运行容器,并返回容器ID。也即启动守护式容器。
/bin/bash 放在镜像名后的是命令,这里我们希望有个交互式Shell,所以用的是/bin/bash。
退出终端使用 exit:
-P 随机端口映射
-p 指定端口映射(-p 宿主机端口:docker内部端口。如:-p 8080:80)
列出当前正在运行的容器
//列出当前所有正在运行的容器
docker ps [option]
-a 列出当前所有正在运行的容器 + 历史上运行过的
-l 显示最近创建的容器
-n 显示最近n个创建的容器
-q 静默模式,只显示容器编号
容器退出、启动、重启、删除
//退出容器
exit 退出,容器停止
ctrl+p+q 退出,容器不停止
//启动已停止运行的容器
docker start 容器ID或者容器名
//重启容器
docker restart 容器ID或者容器名
//停止容器
docker stop 容器ID或者容器名
//强制停止容器
docker kill 容器ID或容器名
//删除已停止的容器
docker rm 容器ID
//强制删除容器
docker rm -f 容器ID
//一次性删除多个容器实例
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
启动守护式容器(后台服务器)
//后台守护式启动
docker run -d 容器名
//redis 前台交互式启动
docker run -it redis:6.0.8
//redis 后台守护式启动
docker run -d redis:6.0.8
在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的后台运行模式。但是有些镜像必须要要有前台进程。如下问题:
问题:以后台模式启动一个容器 docker run -d centos 。然后docker ps -a 进行查看, 会发现容器已经退出。
说明: Docker容器后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀因为他觉得他没事可做了。所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行,常见就是命令行模式,表示我还有交互操作,别中断。
查看容器日志
docker logs 容器ID/名称
查看容器内运行的进程
docker top 容器ID
查看容器内部细节
docker inspect 容器ID
进入正在运行的容器并以命令行交互
//方式一(推荐)
docker exec -it 容器ID /bin/bash
//方式二
docker attach 容器ID
两种方式的区别:
attach 直接进入容器启动命令的终端,不会启动新的进程用exit退出,会导致容器的停止。
exec 是在容器中打开新的终端,并且可以启动新的进程用exit退出,不会导致容器的停止。
从容器内拷贝文件到主机上
docker cp 容器ID:容器内路径 目的主机路径
导入和导出容器
export 导出容器的内容留作为一个tar归档文件[对应import命令]
import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]
//导出
docker export 容器ID > 文件名.tar
//导入
cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
四、Docker镜像
1.镜像生成及发布
Docker镜像commit操作
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
2.镜像发布到阿里云。略…
3.本地镜像发布到私有库
Docker Registry 是 Docker 官方提供的用于构建私有仓库的工具。
3.1 下载、运行
//下载
docker pull registry
//运行。默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射
docker run -d -p 5000:5000 -v /hq/myregistry/:/tmp/registry --privileged=true registry
3.2 规范Tag
将要提交的镜像修改符合私服规范的Tag。
//镜像:Tag Host:Port/Repository:Tag
//使用命令 docker tag 将 xxx:1.1 这个镜像修改为 host:5000/xxx:1.1
docker tag xxx:1.1 172.16.130.8:5000/xxx:1.1
3.3 修改配置文件支持http
docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。修改完后如果不生效,尝试重启docker。
// 在文件/etc/docker/daemon.json 中加上
"insecure-registries": ["172.16.130.8:5000"]
3.4 push推送到私服库
docker push 172.16.130.8:5000/xxx:1.1
3.5 查看私服库中的镜像
curl -XGET http://172.16.130.8:5000/v2/_catalog
3.6 pull到本地并运行
docker pull 172.16.130.8:5000/xxx:1.2
docker run -it 镜像ID /bin/bash
4.虚悬镜像
仓库名、标签都是的镜像,俗称dangling image。
//查看系统中的虚悬镜像
docker image ls -f dangling=true
//虚悬镜像已经失去存在价值,可以删除
docker image prune
Docker Registry
//下载镜像
docker pull registry
//运行私有库Registry,相当于本地有个私有Docker hub
//默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便与宿主机联调
docker run -d -p 5000:5000 -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry
五、Docker容器数据卷
用于Docker容器与宿主机共享数据。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
Docker容器卷的工作就是将docker容器数据通过映射进行备份+持久化到本地的主机目录。
1.命令
//运行一个带有容器卷存储功能的容器实例。-v:volumes
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
上述命令等价于
//运行一个带有读写权限的容器卷存储功能的容器实例
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
即默认支持双向读写。还可以现在容器只能从宿主机读取,不能写。(ro = read only)
//运行一个带有只读权限的容器卷存储功能的容器实例
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
2.卷的继承和共享
下面以容器1和容器2为例,容器2集成了容器1的容器卷规则。这样以来,宿主机、容器1、容器2共享指定目录下的所有数据。
//容器1完成和宿主机的映射
docker run -it --privileged=true -v /mydocker/u:/tmp --name=u1 ubuntu
//容器2继承容器1的卷规则
docker run -it --privileged=true --volumes-from 父类 --name=u2 ubuntu
六、Docker 常规安装简介
1.tomcat安装
//docker hub上面查找tomcat镜像
docker search tomcat
//从docker hub上拉取tomcat镜像到本地
docker pull tomcat
//使用tomcat镜像创建容器实例
docker run -it -p 8080:8080 tomcat
问题及解决方案
(1)可能没有映射端口或者没有关闭防火墙
(2)查看webapps 文件夹是否为空,如果为空,且存在webapps.dist目录,把webapps.dist目录换成webapps。
2.mysql安装
简单版
//运行mysql实例
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
上述方式创建的数据库,在插入中文字符时会报错,因为docker安装的数据库默认字符集为拉丁。
//测试:进入容器
docker psdocker exec -it 容器ID /bin/bash
//测试:进入mysql
mysql -uroot -p
//进入mysql查看字符集,如果不是utf-8,需要修正(默认拉丁)
SHOW VARIABLES LIKE 'character%'
可通过下列“带容器卷安装”的方式解决字符集问题 。
带容器卷安装版
//带容器卷的方式启动
docker run -d -p 3306:3306 --privileged=true -v /hq/mysql/log:/var/log/mysql -v /hq/mysql/data:/var/lib/mysql -v /hq/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name=mysql5.7 mysql:5.7
//新建conf/my.cnf,将配置通过容器卷同步给mysql容器实例
//修改数据库字符集
[client]default_character_set=utf8[mysqld]collation_server = utf8_general_cicharacter_set_server = utf8
3.redis安装
//简单安装
docker run -it --name=redis6 -d -p 6379:6379 redis:6.0.8
七、Docker复杂安装
1.mysql主从安装
1.1 新建主服务器容器实例
1.1.1 新建主服务器容器实例3307
docker run -p 3307:3306 --name=mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
1.1.2 新建my.cnf配置文件
进入 /mydata/mysql-master/conf 目录下新建 my.cnf,内容如下:
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0(单位:天),表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
1.1.3 修改完配置后重启master实例
docker restart mysql-master
1.1.4 创建数据同步用户
//进入mysql-master容器
docker exec -it mysql-master /bin/bash
//进入mysql
mysql -uroot -proot
//master容器实例内创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
//给新建的用户授权
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
1.2 新建从服务器容器实例
1.2.1 新建从服务器容器实例3308
docker run -p 3308:3306 --name=mysql-slave -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
1.2.2 新建my.cnf配置文件
进入/mydata/mysql-slave/conf目录下新建my.cnf,内容如下:
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0(单位:天),表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
1.2.3 修改完配置后重启mysql-slave实例
docker restart mysql-slave
1.2.4 在主数据库中查看主从同步状态
展示的数据在“在从数据库中配置主从复制”中会使用到。
show master status;
1.2.5 在从数据库中配置主从复制
//进入mysql-slave容器
docker exec -it mysql-slave /bin/bash
//进入mysql
mysql -uroot -proot
//从数据库中配置主从复制
change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
主从复制命令参数说明
master_host:主数据库的IP地址
master_port:主数据库的运行端口
master_user:在主数据库创建的用于同步数据的用户账号
master_password:在主数据库创建的用于同步数据的用户密码
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数
master_connect_retry:连接失败重试的时间间隔,单位为秒
1.2.6 在从数据库中查看主从同步状态
//\G参数可选,加上的话状态数据竖着显示,不加横着显示
show slave status \G;
两个No说明还没开始。
1.2.7 在从数据库中开启主从同步
start slave
1.2.8 查看从数据库状态发现已经同步
两个Yes说已开始同步。
1.2.9 主从复制测试
主机新建库-使用库-新建表-插入数据。
从机使用库-查看记录。
2.Redis集群(3主3从)
通过哈希槽Redis集群,实现亿级数据缓存分布式存储。
2.1 创建集群
2.1.1 创建6个redis容器实例
//创建6个redis容器实例
docker run -d --name=redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name=redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name=redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name=redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name=redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name=redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
//参数说明
--net host 使用宿主机的IP和端口,默认
--cluster-enabled yes 开启redis集群
--appendonly yes 开启持久化
2.1.2 进入容器redis-node-1并为6台机器构建集群关系
//进入容器1
docker exec -it redis-node-1 /bin/bash
//注意:进入docker容器后才能执行以下命令
redis-cli --cluster create 172.16.130.8:6381 172.16.130.8:6382 172.16.130.8:6383 172.16.130.8:6384 172.16.130.8:6385 172.16.130.8:6386 --cluster-replicas 1
//参数说明:--cluster-replicas 1 表示为每个master创建一个slave节点
2.1.3 查看集群状态
//进入6381,查看节点状态
redis-cli -p 6381
cluster info
cluster nodes
2.2 数据读写存储
进入1号机写数据,偶发报错。是由于k1、k5不在1号机的哈希槽。
redis-cli -p 6381
set k1 v1
......
为了防止路由失效加参数-c表示以集群的方式连接存储数据
//以集群的方式进入
redis-cli -p 6381 -c
//会根据分配的哈希槽,跳转到对应的主机上。set k1时会跳转到6383
set k1 v1
......
查看集群状态
redis-cli --cluster check 172.16.130.8:6381
2.3 主从扩容案例
3主3从扩容至4主4从
2.4.1 新建两个节点
//新建6387、6388两个节点
docker run -d --name=redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name=redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
2.4.2 将新增的6387作为master节点加入集群
//进入6387容器实例内部
//将新增的6387节点(空槽号)作为master节点加入原集群
redis-cli --cluster add-node 172.16.130.8:6387 172.16.130.8:6381
//检查集群情况,发现机器已加入,但是还未分配槽位
redis-cli --cluster check 172.16.130.8:6381
2.4.3 重新分派槽号
redis-cli --cluster reshard 172.16.130.8:6381
重新分配后发现:
6387是3个新的区间,重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个槽位给新节点6387。
2.4.4 为主节点6387分配从节点6388
命令 redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 172.16.130.8:6388 172.16.130.8:6387 --cluster-slave --cluster-master-id 5f55925f1226bd74894e2f2995d7ed3b4ae9408b
2.4 主从缩容
2.4.1 删除6388
命令 redis-cli --cluster del-node ip:从机端口 从机6388节点ID
//从集群中将4号从节点6388删除
redis-cli --cluster del-node 172.16.130.8:6388 2fc3e5fe599ac66faa28b0aa1741e5a8c21600c9
//将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
2.4.2 槽号重新分配,本例将清出来的槽号都给6381
//将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
redis-cli --cluster reshard 172.16.130.8:6381
2.4.3 删除6387
命令 redis-cli --cluster del-node ip:端口 6387节点ID
redis-cli --cluster del-node 192.168.111.147:6387 5f55925f1226bd74894e2f2995d7ed3b4ae9408b
八、Dockerfile
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段。
![Dockerfile
1.Dockerfile执行流程
- docker从基础镜像运行一个容器。
- 执行一条指令并对容器作出修改。
- 执行类似docker commit的操作提交一个新的镜像层。
- docker再基于刚提交的镜像运行一个新容器。
- 执行 Dockerfile 中的下一条指令直到所有指令都执行完成。
2.指令
- FROM
基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from。 - MAINTAINER
镜像维护者的姓名和邮箱地址。 - EXPOSE
当前容器对外暴露出的端口。 - WORKDIR
指定在创建容器后,终端默认登陆的进来工作目录。 - USER
指定该镜像以什么样的用户去执行,如果都不指定,默认是root。 - ENV
用来在构建镜像过程中设置环境变量。 - ADD
将宿主机目录下的文件拷贝进镜像且会自动解压tar压缩包。 - COPY
类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。 - VOLUME
容器数据卷,用于数据保存和持久化。 - RUN
容器构建时需要运行的命令,在 docker build时运行。
RUN yum -y install vim - CMD
CMD是在docker run 时运行。RUN是在 docker build 时运行。
注意:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。 - ENTRYPOINT
类似于 CMD 指令,但是 ENTRYPOINT 不会被 docker run 后面的命令覆盖,
而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
优点:在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
3.案例
需求:Centos7镜像具备 vim + ifconfig + jdk8。
3.1 下载资源文件
3.2 编写Dockerfile文件
新建Dockerfile文件,并写入如下内容。
FROM centos:7
MAINTAINER demo<demo@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD是相对路径jar,把jdk-xxx.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u371-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_371
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD /bin/bash
3.3 构建
//命令格式:docker build -t 新镜像名字:TAG .
docker build -t centosjava8:1.5 .
注意:注意,上面TAG后面有个空格,有个点。
3.4 运行
//docker run -it 新镜像名字:TAG
docker run -it mycentosjava8:1 /bin/bash
4.Docker中部署微服务
4.1 在idea中新建微服务
在idea中新建微服务,打包后拷贝到工作根目录中。
4.2 新建Dockerfile文件
在jar包同级目录新建 Dockerfile文件,内容如下:
# 基础镜像使用java8
FROM java:8
# 作者
MAINTAINER demo
# 在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为zzyy_docker.jar
ADD Docker_test-0.0.1-SNAPSHOT.jar docker_test.jar
# 运行jar包
RUN bash -c 'touch /docker_test.jar'
ENTRYPOINT ["java","-jar","/docker_test.jar"]
#暴露7001端口作为微服务
EXPOSE 7001
4.3 构建镜像文件
docker build -t docker_test:1.0
4.4 启动服务
docker run -d -p 7001:7001 docker_test:1.0
九、Docker网络
创建完docker后,会默认创建3大网络模式:bridge、host、none。
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,用于docker与宿主机及docker与docker之间的通信。此主机上启动的Docker容器都会连接到这个虚拟网桥上,这样主机上的所有容器就通过交换机连在了一个网络中。
docker network 的作用
- docker容器间的互联和通信以及端口映射。
- 容器IP变动时,可以通过服务名直接进行网络通信。
1.Docker网络模式
1.1 bridge模式
bridge模式是docker的默认网络模式,使用–network bridge指定,不写时默认使用docker0。为每一个容器分配、设置IP,并将容器连接到 docker0 虚拟网桥。
- Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
- docker run的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。
- 网桥docker0创建一对对等虚拟设备接口。docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对。
- 综上,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。
1.2 host模式
使用–network host指定。
- 容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。
- 容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
1.3 none模式
极少用。使用–network none指定。
在none模式下,Docker容器拥有自己的Network Namespace,但是并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
1.4 container模式
新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等。使用–network container : NAME或者容器ID指定。不过,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
//创建a1实例
docker run -it --name=a1 alpine /bin/sh
//创建a2实例,但使用a1的网卡配置
docker run -it --network container:a1 --name=a2 alpine /bin/sh
//都运行后进入容器可发现二者ip一致
1.5 自定义网络模式
同一个网段的容器间,按照IP地址ping是可以的,但是按照服务名称就无法ping通,而通常容器只要重启IP地址会重新分配。
自定义网络本质就维护好了主机名和ip的对应关系(ip和域名都能通),可以解决服务名称无法ping通的问题。
//新建自定义网络
docker network create test_network
//新建容器加入上一步新建的自定义网络
docker run -d -p 8081:8080 --network test_network --name=tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network test_network --name=tomcat82 billygoo/tomcat8-jdk8
//进入容器测试能否ping通
ping tomcat81
ping tomcat82
2.常用命令
//查看网络
docker network ls
//查看网络源数据
docker network inspect 网络名字
//删除网络
docker network rm 网络名字
//连接网络
connect
//创建网络
create
//中断网络
disconnect
//删除所有无效不再用的网络
prune
十、Docker-compose容器编排
官网
官网下载
Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。
Compose允许用户通过一个单独的docker-compose.yml模板文件来定义一组相关联的应用容器为一个项目。
Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。只要一个命令,就能同时启动/关闭这些容器。
1.安装
//下载安装
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
//放开读写权限
chmod +x /usr/local/bin/docker-compose
//查看版本
docker-compose --version
//如果使用curl的方式安装,则如下卸载
rm /usr/local/bin/docker-compose
2.Compose常用命令
docker-compose -h # 查看帮助
docker-compose up # 启动所有docker-compose服务
docker-compose up -d # 启动所有docker-compose服务并后台运行
docker-compose down # 停止并删除容器、网络、卷、镜像。
docker-compose exec yml里面的服务id # 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps # 展示当前docker-compose编排过的运行的所有容器
docker-compose top # 展示当前docker-compose编排过的容器进程
docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose config # 检查配置
docker-compose config -q # 检查配置,有问题才有输出
docker-compose restart # 重启服务
docker-compose start # 启动服务
docker-compose stop # 停止服务
十一、Portainer
官网
Portainer 是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。
安装
# --restart=always 意思是在docker服务启动的时候随其一起启动
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
访问
http://172.16.130.8:9000/