linux内
ctrl+a fn+home 开头
ctrl+e fn+end 结尾
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["个人阿里云容器镜像地址"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker search xxxx
docker limit 5 search xxx
docker network ls
docker images
docker images -q
-
docker images -a
docker images -aq
docker pull docker
docker system df docker stats
docker ps -a -q | xargs docker rm
docker rm -f $(docker ps -a -q) docker ps -a -q | xargs docker rm
docker images |grep [条件] |awk '{print $3}' |xargs -I {} docker rmi {}
仓库名 镜像id 都是none 构建或者删除镜像时候会出现一些错误导致虚悬镜像 俗称dangling image 查看全部虚悬镜像 docker images ls -f dangling=true 删除全部虚悬镜像 docker images prune
docker ps docker ps -a docker ps -q docker ps -l docker ps -n 3
启动容器 交互式启动 docker run -it 镜像id 镜像名称:tags docker run -it ubuntu /bin/bash docker run -it --name=mylinux ubuntu /bin/bash docker run -it --name=mylinux ubuntu bash docker run -it --name=redis6 redis:6.0.8
守护式(有的才可以 有的无操作会自杀) docker run -d redis:6.0.8
默认最新latest 加tag版本 docker run -it centos:7 /bin/bash
docker info
docker run --help 或者 man docker-run
退出容器:
exit run进去容器,exit退出,容器停止
ctrl+p+q run进去容器,ctrl+p+q退出,容器不停止
启动停止的容器
docker start 容器id/容器名 docker start a902c39295a7进入已经启动的容器 伪终端 docker exec -it 容器名或id /bin/bash
docker attach 容器id/容器名
attach 直接进入容器启动命令的终端,不会启动新的进程 用exit退出,会导致容器的停止。
exec 是在容器中打开新的终端,并且可以启动新的进程 用exit退出,不会导致容器的停止。
停止容器 docker stop 容器id/容器名
强制停止容器 docker kill 容器id/容器名
run是直接创建新的容器,start是启动已有的???
删除容器 -f强制 docker -rm 容器id/名字 docker -rm -f 容器id/名字
删除镜像 docker rmi 镜像id docker rmi 镜像名称:tag
删除多个容器 docker rm -f $(docker ps -a -q) docker ps -a -q | xargs docker rm
查看容器日志 docker logs names/容器id
查看容器运行进程 docker top 容器Id/name
查看容器内部细节 docker inspect 容器ID/名字
从容器内拷贝文件到主机上 docker cp 容器ID:容器内路径 目的主机路径 在本机运行 docker cp d636a691e6eb:/root/aa.txt ~/ docker cp d636a691e6eb:/root/aa.txt ~/qq.txt
导出容器 export 导出容器的内容留作为一个tar归档文件[对应import命令] docker export 容器id > abcd.tar docker export 容器名 > abcd.tar
导入容器 import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export] cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
cat cetos7.tar | docker import - centos:7
在容器系统安装新的命令内容后完成后,commit我们自己的新镜像(无关容器是否在运行) docker commit -m="描述信息" -a="作者" 容器id 要创建的目标镜像名:tag docker commit -m="描述信息" -a="作者" 容器名 要创建的目标镜像名:tag
docker commit -m="add vim cmd" -a="zzz" b895bc9af7f4 centos:7.8
将本地镜像推送到阿里云
- 登录阿里云Docker Registry $ docker login --username=阿里云账号 registry.cn-hangzhou.aliyuncs.com 用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。
-
从Registry中拉取镜像 $ docker pull registry.cn-hangzhou.aliyuncs.com/路径仓库/centos:[镜像版本号]
-
将镜像推送到Registry $ docker login --username=阿里云账号 registry.cn-hangzhou.aliyuncs.com $ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/路径仓库/centos:[镜像版本号] $ docker push registry.cn-hangzhou.aliyuncs.com/路径仓库/centos:[镜像版本号] 请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。
-
选择合适的镜像仓库地址 从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。
如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。
- 示例 使用"docker tag"命令重命名镜像,并将它通过专有网络地址推送至Registry。
$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE registry.aliyuncs.com/acs/agent 0.7-dfb6816 37bb9c63c8b2 7 days ago 37.89 MB $ docker tag 37bb9c63c8b2 registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816 使用 "docker push" 命令将该镜像推送至远程。
$ docker push registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
本地镜像发布到私有库流程
是什么 1 官方Docker Hub地址:https://hub.docker.com/,中国大陆访问太慢了且准备被阿里云取代的趋势,不太主流。
2 Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。
3 Docker Registry是官方提供的工具,可以用于构建私有镜像仓库
流程:
1、下载镜像Docker Registry docker pull registry
2、运行私有库Registry,相当于本地有个私有Docker hub docker run -d -p 5000:5000 -v 主机目录:容器目录 --privileged=true 镜像名称/id docker run -d -p 5000:5000 -v /dockerzou/myregistry/:/tmp/registry --privileged=true registry #默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调
3、案例演示创建一个新镜像,centos安装ifconfig命令 公式: docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名] 命令:在容器外执行,记得 docker commit -m="ifconfig cmd add" -a="zzz" 137e639dd8e6 centos:1.9f
4、curl验证私服库上有什么镜像 curl -XGET http://ip:5000/v2/_catalog curl -XGET localhost:5000/v2/_catalog
5、将新镜像zzyyubuntu:1.2修改符合私服规范的Tag 按照公式: docker tag 镜像:Tag Host:Port/Repository:Tag 自己host主机IP地址 使用命令 docker tag 将zzyyubuntu:1.2 这个镜像修改为192.168.111.162:5000/zzyyubuntu:1.2 docker tag centosn1:1.9f localhost:5000/centosif:1f docker tag centosn1:1.9f 内ip1:5000/centosif:1f
6、修改配置文件使之支持http 这里是localhost还是具体ip看上下操作统一配置 vim /etc/docker/daemon.json { "registry-mirrors": ["https://aa25jngu.mirror.aliyuncs.com"], "insecure-registries": ["localhost:5000"] }
7、push推送到私服库 docker push ip:5000/centosif:1f docker push localhost:5000/centosif:1f
8、curl验证私服库上有什么镜像 curl -XGET http://ip:5000/v2/_catalog curl -XGET localhost:5000/v2/_catalog
9、pull到本地并运行
查看: curl http://仓库IP:5000/v2/_catalog curl http://仓库IP:5000/v2/镜像名称/tags/list curl -XGET http://registry:5000/v2/镜像名字/tags/list 这个可以查看镜像的tag curl -XGET http://ip:5000/v2/centosif/tags/list curl -XGET http://localhost:5000/v2/centosif/tags/list 拉取:
Docker容器数据卷
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied 解决办法:在挂载目录后多加一个--privileged=true参数即可 如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为, 在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即 使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
- 将运用与运行的环境打包镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的
Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。 为了能保存数据在docker中我们使用卷。
特点: 1:数据卷可在容器之间共享或重用数据 2:卷中的更改可以直接实时生效,爽 3:数据卷中的更改不会包含在镜像的更新中 4:数据卷的生命周期一直持续到没有容器使用它为止
直接命令添加: docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名 docker run -it --privileged=true -v /tmp/docker:/tmp/docker --name=centosgz 95df038ab125 /bin/bash
查看是否挂载成功 docker inspect 容器ID
容器和宿主机之间数据共享 1 docker修改,主机同步获得 2 主机修改,docker同步获得 3 docker容器stop,主机修改,docker容器重启看数据是否同步。
读写规则映射添加说明(目录没有会自动创建) 读写(默认): docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
只读:(容器内对此只能读,本机对其无限制) 容器实例内部被限制,只能读取不能写 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名 docker run -it --privileged=true -v /tmp/docker2:/tmp/docker2:ro --name=centosgrz 95df038ab125 /bin/bash
卷的继承和共享(无论哪个容器挂了再重启数据期间数据也会同步过去)
1、容器1完成和宿主机的映射 docker run -it --privileged=true -v /tmp/docker:/tmp/u1 --name=centos 95df038ab125 /bin/bash 2、容器2继承容器1的卷规则 docker run -it --privileged=true --volumes-from 父类容器 --name=centos2 镜像 [option]
docker run -it --privileged=true --volumes-from centos --name=centos2 95df038ab125 /bin/bash
Docker常规安装
tomcat 总体步骤: 1、搜索镜像 docker hub 上面找 或 docker search tomcat 2、拉取镜像 docker pull tomcat 3、查看镜像 docker images tomcat 4、启动镜像 端口映射 数据卷挂载 docker run -it -p 主机端口:容器端口 tomcat -p 小写,主机端口:docker容器端口 -P 大写,随机分配端口 i:交互 t:终端 d:后台 docker run -it -p 8089:8080 --name=tomcat tomcat
docker run -d -p 8089:8080 --name=tomcat tomcat 5、停止容器 6、移除容器 特殊版 docker pull billygoo/tomcat8-jdk8 docker run -d -p 8089:8080 --name mytomcat8 billygoo/tomcat8-jdk8mysql(简单版本) docker pull mysql:5.7 docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=z123456 -d mysql:5.7 docker ps -a docker exec -it 容器ID /bin/bash mysql -uroot -p
博客版 docker run -id -p 3306:3306 --name=c_mysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=z123456 mysql:5.7 docker run -id -p 80:8099 -v $PWD/blog/upload:/opt/blog/upload blog
docker上默认字符集编码隐患(中文乱码)!!! docker里面的mysql容器实例查看 SHOW VARIABLES LIKE 'character%';
mysql(实战版本)(容器数据卷可挂载多个) show variables like '%datadir%';查看数据目录结构 SHOW VARIABLES LIKE 'character%';查看字符集 show variables like 'log_%'; 查看是否开启binlog
docker run -d -p 3306:3306 --privileged=true -v /dockershare/mysql/log:/var/log/mysql -v /dockershare/mysql/data:/var/lib/mysql -v /dockershare/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql:5.7
在目录/dockershare/mysql/conf:/etc/mysql/conf.d下 vim my.cnf
[client] default_character_ set=utf8 [mysqld] collation_server = utf8_general_ci character_set_server = utf8
redis
docker pull redis:6.0.8
docker run -d -p 6379:6379 --name=redis redis:6.0.8
docker exec -it redis /bin/bash
redis-cli
set k1 v1 get k1
ping
在CentOS宿主机下新建目录/app/redis
mkdir -p /app/redis 将一个redis.conf文件模板拷贝进/app/redis目录下 /app/redis目录下修改redis.conf文件
允许redis外地连接 必须 注释掉 # bind 127.0.0.1
允许redis外地连接 必须 注释掉 # bind 127.0.0.1
daemonize no 将daemonize yes注释起来或者 daemonize no设置,因为该配置和docker run中-d参数冲突,会导致容器一直启动失败
开启redis数据持久化 appendonly yes 可选
创建容器 docker run -p 6379:6379 --name=redis --privileged=true -v /dockerredis/redis/redis.conf:/etc/redis/redis.conf -v /dockerredis/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
docker exec -it 运行着Rediis服务的容器ID redis-cli docker exec -it redis /bin/bash redis-cli 选择第index个 redis库 redis.conf默认16 即select 15 select 15
高级篇
mysql 主从搭建步骤
1、新建主服务器容器实例3307 docker run -p 3307:3306 --name=mysql-master --privileged=true -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
2、进入/mydata/mysql-master/conf目录下新建my.cnf vim 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错误是因为主从数据库数据不一致
slave_skip_errors=1062
3、修改完配置后重启master实例 docker restart mysql-master
4、进入mysql-master容器
5、master容器实例内创建数据同步用户(创建用户 授权) CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'slave'@'%';
6、新建从服务器容器实例3308 docker run -p 3308:3306 --name=mysql-slave --privileged=true -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
7、进入/mydata/mysql-slave/conf目录下新建my.cnf vim 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
8、修改完配置后重启slave实例 docker restart mysql-slave
9、在主数据库中查看主从同步状态 show master status;
10、进入mysql-slave容器 docker exec -it mysql-slave /bin/bash mysql -uroot -proot
11、在从-数据库中配置主从复制(进入从机容器进入数据库中) ip1 内ip1 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; change master to master_host='ip1', 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:连接失败重试的时间间隔,单位为秒。
12、在从-数据库中查看主从同步状态 show slave status \G;
13、在从-数据库中开启主从同步 start slave;
14、查看从-数据库状态发现已经同步 show slave status \G; 15、主从复制测试
Redis 集群
新建6个docker容器 redis实例 --net host 使用宿主机的IP和端口,默认; --privileged=true 获取宿主机root用户权限; --cluster-enabled yes 开启redis集群; --appendonly yes 开启持久化; --port 6386 redis端口号
docker run -d --name redis-node-1 --net host --privileged=true -v /dockerredis/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 /dockerredis/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 /dockerredis/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 /dockerredis/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 /dockerredis/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 /dockerredis/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
进入容器redis-node-1并为6台机器构建集群关系 docker exec -it redis-node-1 /bin/bash
构建主从关系: //注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址 redis-cli --cluster create ip1:6381 ip1:6382 ip1:6383 ip1:6384 ip1:6385 ip1:6386 --cluster-replicas 1 redis-cli --cluster create 内ip1:6381 内ip1:6382 内ip1:6383 内ip1:6384 内ip1:6385 内ip1:6386 --cluster-replicas 1
--cluster-replicas 1 表示为每个master创建一个slave节点
链接进入6381作为切入点,查看节点状态 redis-cli -p 6381 cluster info cluster nodes
数据读写存储 启动6机构成的集群并通过exec进入 对6381新增两个key 防止路由失效加参数-c并新增两个key redis-cli -p 6381 -c 查看集群信息 (进入容器、没进入redis时) redis-cli --cluster check 内ip1:6381
主从扩容
新建6387、6388两个节点+新建后启动+查看是否8节点 docker run -d --name redis-node-7 --net host --privileged=true -v /dockerredis/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 /dockerredis/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
进入6387容器实例内部 docker exec -it redis-node-7 /bin/bash
将新增的6387节点(空槽号)作为master节点加入原集群 将新增的6387作为master节点加入集群 redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381 redis-cli --cluster add-node 内ip1:6387 内ip1:6381
6387 就是将要作为master新增节点 6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群
检查集群情况第1次 redis-cli --cluster check 真实ip地址:6381 redis-cli --cluster check 内ip1:6381
重新分派槽号 80fa65a0b506b74bae2f1110633300c17ddabbd8 命令:redis-cli --cluster reshard IP地址:端口号 redis-cli --cluster reshard 内ip1:6381 计算重新平均后的槽位数量 16384处于master台数 输入节点id all
检查集群情况第2次 redis-cli --cluster check 内ip1:6381
槽号分派说明 为什么6387是3个新的区间,以前的还是连续? 重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387
为主节点6387分配从节点6388 命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 内ip1:6388 内ip1:6387 --cluster-slave --cluster-master-id 80fa65a0b506b74bae2f1110633300c17ddabbd8
这个是6387的编号,按照自己实际情况
检查集群情况第3次(6381等几台master主机找谁都可以) redis-cli --cluster check 内ip1:6382
主从缩容
检查集群情况1获得6388的节点ID redis-cli --cluster check 内ip1:6382
将6388删除 从集群中将4号从节点6388删除
命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID redis-cli --cluster del-node 内ip1:6388 ee9b7b3c162b2957f94480af09468f2ab1a70196 检查节点情况 redis-cli --cluster check 内ip1:6382
将6387的槽号清空,重新分配,本例将清出来的槽号都给6381 redis-cli --cluster reshard 内ip1:6381 全给 4096 接收的id 116355df7c7c5e39b6994706f65cd7a8eb022809 移除的id 80fa65a0b506b74bae2f1110633300c17ddabbd8 done yes
检查集群情况第二次 redis-cli --cluster check 内ip1:6381
4096个槽位都指给6381,它变成了8192个槽位,相当于全部都给6381了,不然要输入3次,全给了
命令:redis-cli --cluster del-node ip:端口 6387节点ID redis-cli --cluster del-node 内ip1:6387 80fa65a0b506b74bae2f1110633300c17ddabbd8
检查集群情况第三次 redis-cli --cluster check 内ip1:6381
DockerFile解析
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
官网https://docs.docker.com/engine/reference/builder/
构建三步骤 编写Dockerfile文件 docker build命令构建镜像 docker run依镜像运行容器实例
Dockerfile内容基础知识 1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数 2:指令按照从上到下,顺序执行 3:#表示注释 4:每条指令都会创建一个新的镜像层并对镜像进行提交
Docker执行Dockerfile的大致流程 (1)docker从基础镜像运行一个容器 (2)执行一条指令并对容器作出修改 (3)执行类似docker commit的操作提交一个新的镜像层 (4)docker再基于刚提交的镜像运行一个新容器 (5)执行dockerfile中的下一条指令直到所有指令都执行完成
DockerFile常用保留字指令
FROM 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令 两种格式 shell格式 RUN yum -y install vim RUN <命令行命令> exec格式 RUN ["可执行文件","参数一","参数二"] RUN是在 docker build时运行
EXPOSE 当前容器对外暴露出的端口 WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点 USER 指定该镜像以什么样的用户去执行,如果都不指定,默认是root ENV 用来在构建镜像过程中设置环境变量 ADD 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包 COPY 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置 VOLUME 容器数据卷,用于数据保存和持久化工作
CMD 指定容器启动后的要干的事情 两种格式 shell格式 exec格式 Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 可参考官网Tomcat的dockerfile演示讲解 它和前面RUN命令的区别 :CMD是在docker run 时运行。 RUN是在 docker build时运行。
ENTRYPOINT ENTRYPOINT ["
","参数1","参数2",...] 也是用来指定一个容器启动时要运行的命令 类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序 ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。 当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 " " 优点:在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。 注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。 BUILD Both RUN FROM WORKDIR CMD MAINTAINER USER ENV COPY EXPOSE ADD VOLUME RUN ENTRYPOINT ONBUILD .dockerignore
案例 自定义镜像mycentosjava8 要求 Centos7镜像具备vim+ifconfig+jdk8 JDK的下载镜像地址 https://mirrors.yangxingzhen.com/jdk/
编写 准备编写Dockerfile文件 创建目录myfile 将jdk上传到目录下 在目录下编写Dockerfile
FROM centos:7 MAINTAINER zzyyzzyybs@126.com
ENV MYPATH /usr/local WORKDIR $MYPATH
#安装vim编辑器 RUN yum -y install vim #安装ifconfig命令查看网络IP RUN yum -y install net-tools #安装java8及lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/ #配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_171 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 echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash
构建镜像 docker build -t 新镜像名字:TAG . docker build -t centosjava8:1.5 . docker build -f ./mydockerfile -t centosjava82:2 . 不指定版本默认lastest 换名字非Dockerfile 需要-f 指定目录和dockerfile文件名
运行镜像 docker run -it 新镜像名字:TAG docker run -it centosjava8:1.5 /bin/bash
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统, 联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
仓库名 镜像id 都是none 构建或者删除镜像时候会出现一些错误导致虚悬镜像 俗称dangling image 查看全部虚悬镜像 docker images ls -f dangling=true 删除全部虚悬镜像 docker images prune
写一个例如: vim DOckerfile
from ubuntu CMD echo 'action is success'
docker build . 查看 docker image ls -f dangling=true 删除 docker image prune
--restart=always 容器随着docker重启而重启
如果创建容器的时候忘了写,也可以用docker update ID --restart=always
docker compose config -q 检查语法
Docker网络
容器间的互联和通信以及端口映射;容器IP变动时候可以通过服务名直接网络通信而不受到影响
查看全部命令 docker network --help 查看网络 docker network ls 创建网络 XXX网络名字 docker network create aaa 删除网络XXX网络名字 docker network rm aaa 查看网络源数据 XXX网络名字 docker network inspect bridge docker network inspect u1 | tail -n 20
bridge 使用--network bridge指定,默认使用docker0 为每一个容器分配、设置IP等,并将容器连接到一个docker0,虚拟网桥,默认为该模式。 eg:不是停止就回收ip,而是要删除才会回收,并且要另一个容器重新启动,才会重新分配 Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0, 它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。 Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。 1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。 因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。 2 docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig, 就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址 3 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。 3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair); 3.2 每个容器实例内部也有一块网卡,每个接口叫eth0; 3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。 通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。 查看 bridge 网络的详细信息,并通过 grep 获取名称项 docker network inspect bridge | grep name
host 使用--network host指定 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。 直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。 容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
none 使用--network none指定 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,IP等。 在none模式下,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo需要我们自己为Docker容器添加网卡、配置IP等。
container 使用--network container:NAME或者容器ID指定 新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等 新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP, 而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。 eg:
docker run -it --name alpine1 alpine /bin/sh docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh
自定义网络
自定义桥接网络,自定义网络默认使用的是桥接网络bridge 新建自定义网络 docker network create 网络名称 新建容器加入上一步新建的自定义网络 docker run -d -p 8081:8080 --network zzyy_network --name tomcat81 billygoo/tomcat8-jdk8 docker run -d -p 8082:8080 --network zzyy_network --name tomcat82 billygoo/tomcat8-jdk8 互相ping测试Docker-compose容器编排
Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。 你需要定义一个 YAML 格式的配置文件docker-compose.yml, 写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器
docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?
如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具
例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。。。。。。
Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
下载 https://docs.docker.com/compose/compose-file/compose-file-v3/ https://docs.docker.com/compose/install/ 安装(新版的 自带dockercompose docker compose version 可查看版本) 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安装的) sudo rm /usr/local/bin/docker-compose
一文件 docker-compose.yml 两要素 服务(service):一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器 工程(project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
Compose使用的三个步骤 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务。 最后,执行docker-compose up命令 来启动并运行整个应用程序,完成一键部署上线
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 # 停止服务
Compose编排微服务 编写docker-compose.yml文件 eg:
version: "3"
services: microService: image: zzyy_docker:1.6 container_name: ms01 ports: - "6001:6001" volumes: - /app/microService:/data networks: - atguigu_net depends_on: - redis - mysql
redis: image: redis:6.0.8 ports: - "6379:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:/data networks: - atguigu_net command: redis-server /etc/redis/redis.conf
mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: '123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'db2021' MYSQL_USER: 'zzyy' MYSQL_PASSWORD: 'zzyy123' ports: - "3306:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - atguigu_net command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
networks: zdy:
使用的
version: "3"
services: microService: image: blog:1 container_name: m_blog ports: - "8099:8099" volumes: - /myfiles/blog/upload:/opt/blog/upload networks: - zdy depends_on: - mysql
mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: 'z123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' container_name: m_mysql ports: - "3306:3306" volumes: - /myfiles/mysql/conf:/etc/mysql/conf.d - /myfiles/mysql/logs:/logs - /myfiles/mysql/data:/var/lib/mysql - /myfiles/mysql/conf/my.cnf:/etc/my.cnf - /myfiles/mysql/init:/docker-entrypoint-initdb.d networks: - zdy command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
networks: zdy:
在文件目录下 执行 docker-compose up 或者 执行 docker-compose up -d