docker
docker底层原理
Docker是什么工作的?
- Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
- DockerServer接收到Docker-Client的指令,就会执行这个命令!
Docker为什么比 VM快?
- Docker有着比虚拟机更少的抽象层。
- docker利用的是宿主机的内核,vm需要是GuestOs
所以说,新建一个容器的时候,docker不需要想虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest 0S,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!
docker三大核心:镜像(image)、容器(container)、仓库(repository)
docker安装
1. 卸载旧的版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
2. 安装docker前需要安装的依赖包:
yum install -y yum-utils device-mapper-persistent-data lvm2
3. 使用阿里国内镜像源安装docker
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum list docker-ce --showduplicates | sort -r
yum makecache fast
yum install docker-ce -y
4. 安装docker
yum install docker-ce docker-ce-cli containerd.io
5. 启动docker
systemctl start docker
docker version
启动hello-world镜像
docker run hello-world
卸载docker:
yum remowe docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker/ docker默认工作目录
阿里云镜像加速:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://dlmlq6wm.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
镜像命令:
docker images
docker images -qa 查找所有镜像
docker history 查看镜像制作历史
docker inspect 查看镜像详细信息
docker rmi 删除本地镜像(镜像创建容器后,最后一份镜像不能删)
docker save 镜像另存为tar包
docker save xx:tag -o aa.tar
docker load 使用tar包导入镜像
docker load -i aa.tar
docker search 搜索镜像
docker tag 修改镜像名称和标签
docker tag xx:tag AA:cc
docker inspect 查看镜像底层信息
docker rmi -f $(docker images -qa) #删除镜像
commit制作镜像
docker commit提交容器成为一个新的副本
#命令和git原理类似
docker commit -m="提交的描述信息" -a="作者” 容器id 目标镜像名:[TAG]
docker commit -m="add webapps app" -a="Jason" 7d8b079a66a8 tomcat02:1.0
容器命令:
启动容器
docker run [可选参数] image
参数说明
--name='Name' 容器名字
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p 主机端口:容器端口
-p ip:主机端口:容器端口
-p 容器端口
-P(大P) 随机指定端口
docker run -it 镜像名:TAG (-itd放后台运行)
docker run -it centos /bin/bash 启动并进去容器
douker ps 命令 #列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q 只显示容器id
-aq 显示所有启动过的容器id
docker stop/start/restart
docker kill 容器id # 强制停止当前容器
docker attach 容器id 启动后停止,可用Crtl + P + Q #容器不停止退出
docker exec -it 容器id /bin/bash
docker top 在容器外查看容器内执行命令(相当于在容器内执行ps)
docker inspect 容器id 查看容器详细信息
docker rm 容器id #删除指定容器,强制删除需要rm -f,容器停止后才可以删
docker rm $(docker stop 容器id) 删除单个容器
docker rm $(docker ps -aq) 删除所有容器。后面命令执行的结果可以作为前面命令的参数
docker ps -a -q|xargs docker rm #删除所有容器
docker pull
docker push 镜像名称:标签
docker commit 容器it aa:cc 将容器前端盘做成镜像
重启容器服务
只有将启动的容器都关闭后才可以重启容器服务,否则会假死
从容器内拷贝文件到主机
docker cp 容器id:容器内路径 主机路径
常用其他命令
后台启动容器
命令docker run -d 镜像名!
[root@kuangshen /]# docker run -d centos
#间题docker ps,发现centos停止了
#常见的坑: docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
启动容器并写入脚本
docker run -d centos /bin/sh -c "while true;do echo 1;sleep 1;done"
查看容器日志
docker logs -tf --tail 10 容器ID
测试
安装nginx
docker run -d --name nginx_01 -p 3344:80 nginx
curl localhost:3344
docker exec -it nginx_01 /bin/bash
root@35152e5d6719:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
安装Tomcat
#官方的使用
docker run -it --rm tomcat:9.0 # --rm 一般用来测试,用完就删除
docker pull tomcat
docker run -d --name tomcat01 -p 3355:8080 tomcat
root@7d8b079a66a8:/usr/local/tomcat# cp -r webapps.dist/* webapps 将webapps.dist内容拷贝到webapps目录下
#发现问题:
1、1inux命令少了
2。没有webapps。
阿里云镜像的原因。默认是最小的镜像,所有不必要的都剔除掉。#保证最小可运行的环境!
作业:部署es + kibana
# es暴露的端口很多
# es十分的耗内存
# es的数据―般需要放置到安全目录!挂载
#启动了 linux就卡住了
docker stats 容器ID #查看cpu的状态
启动elasticsearch
增加内存的限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms65m -Xms512m" elasticsearch:7.6.2
#测试一下es是够成功了
[root@kuangshen home]# curl localhost:9200
可视化
portainer(先用这个)
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Rancher ( CICD再用)
什么portainer ?
Docker图形化界面管理工具!提供—个后台面板供我们操作!
docker run -d -p 8088 :9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:http://ip:8088/
dockerfile语法格式:
FROM #基础镜像
MAINAIENR #镜像创建者信息
EXPOSE #开放的端口
ENV #设置变量
ADD #复制文件到镜像
ADD xxx xxx
RUN #制作镜像时执行的命令,可以有多个
WORKDIR #定义容器默认工作目录
CMD #容器启动时执行的命令(/bin/bash),仅可以只有一条CMD命令
["/usr/sbin/python","-D"]
VOLUME # 挂载的目录
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile 这个时候就会运行ONBUILD的指令。触发指令。
COPY #类似ADD ,将我们文件拷贝到镜像中
docker build -t aa:cc . (-t指定镜像名称 .表示当前目录 且当前目录下必须有dockerfile文件)
设置主机名环境变量
set |grep ps1
PS1='[/u @/h/W]\$'
dockerfile示例:
[webserver@docker1 cc]# cat run .sh
#!/bin/bash
/usr/sbin/sshd -D &
/usr/sbin/httpd -DFOREGROUND
[webserver@docker1 cc]# chmod 755 run .sh
[webserver@docker1 cc]# cat Dockerfile
FROM myos:sshd
RUN yum install -y httpd
WORKDIR /var/ www / html
ENV EnvironmentFile=/etc/sysconfig/httpd
ENV PS1="[webserver@\h lW]1$'
ADD index.html index.html
EXPOSE 80
EXPOSE 22
ADD run.sh /etc/init.d/run.sh
CMD ["/etc/init.d/run.sh"]
镜像仓库distribution
登录docker hub并且push自己的镜像到服务器
[root@VM-0-14-centos dockerfile]# docker login -u 769635609
阿里云镜像服务上
1、登录阿里云
2、找到容器镜像服务
3、创建命名空间
4、创建容器镜像
5、浏览阿里云
示例
使用"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
启动镜像
docker run -it 仓库ip:端口/镜像名称:标签
仓库ip和端口可不写
1、创建一个镜像仓库( 192.168.1.30)
yum install docker-distribution.x86_64
systemctl start docker-distribution.service
systemctl enable docker-distribution.service
http://192.168.1.30:5000/v2/_catalog
2、给仓库上传镜像(192.168.1.31上传)
修改/etc/sysconfig/docker
ADD_REGISTRY='--add-registry 192.168.1.30:5000’
INSECURE_REGISTRY=’--insecure-registry 192.168.1.30:5000’
停止所有容器docker stop id
重启服务systemctl restart docker
docker tag busybox :latest 192.168.1.30:5000/busybox :latest
docker push 192.168.1.30:5000/busybox:latest
3、所有客户机配置使用新的镜像仓库,启动容器(192.168.1.32)同上第2部分配置文件
启动容器docker run '-it [192.168.1.30:5000/]myos:latest
容器持久化存储
使用数据卷 映射目录 -v
方式一:直接使用命令来挂载-V
docker run -it -v 主机目录:容器内目录 镜像名
#测试
[root@kuangshen home]# docker run -it -v /home/ceshi:/home centos /bin/bash
#启动起来时侯我们可以通过docker inspect 容器id
实战:安装MysQL
思考:MySQL的数据持久化的问题!
#获取镜像
[root@kuangshen home] # docker pull mysql:5.7
#运行容器,需要做数据挂载!#安装启动mysq1 ,需要配置密码的,这是要注意点!
-d后台运行 -p端映射 -卷挂载 -e环境配置 --name容器名字
[root@kuangshen home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/1ib/mysql -e MYSQL_RO0T_PASSWORD=123456 --name mysql01 mysql:5.7
具名和匿名挂载
#匿名挂载
-v 容器内路径! -P 随机端口
docker run -d -P --name nginx01 -v /etc/nginx nginx:latest
#查看所有的volume的情况
[root@kuangshen home]# docker volume ls
#这里发现,这种就是匿名挂载,我们在-v只写了容器内的路径,没有写容器外的路径!
#具名挂载:
#通过 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v jason-ngxin:/etc/nginx nginx:latest
[root@VM-0-14-centos ~]# docker volume ls
DRIVER VOLUME NAME
local ad9d64cae99f45d39ac7275157ad4b81460effbe6af2b0bc3cd53fcf70ae39ef
local jason-ngxin
inspect 查看详细信息
[root@VM-0-14-centos ~]# docker volume inspect jason-ngxin
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的`具名挂载’
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂戟!
拓展:
#通过-v容器内路径:ro rw 改变读写权限
ro readonly #只读
rw readwrite #可读可写
#—旦这个了设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
--volumes-form 多个mysql实现数据共享
[root@kuangshen home]# docker run -d -p 3310:3306 -v /etc/mysq1/conf.d -v /var/Tib/mysq1 -eMYSOL_ROOT_PASSWORD=123456 --name mysq10i mysql :5.7
[root@kuangshen home]# docker run -d -p 3310:3306 -e MYsQL_ROOT_PASSIORD=123456 --name mysq102 --volumes-form mysq101 mysq7 : 5.7
#这个时候,可以实现两个容器数据同步!
结论∶
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!|
实现nfs共享文件
192.168.1.30
yum install nfs-utils
编辑/etc/exports
mkdir /var/webroot
chmod 777 /var/webroot
systemctl start nfs
docker1
yum install nfs-utils
mount -t nfs 192.168.1.30:/ var/webroot /mnt
docker run -itd -v /mnt:/usr/share/nginx/html docker.io/nginx:latest
docker2:
yum install nfs-utils
mount -t nfs 192.168.1.30:/var/webroot /mnt
docker run -itd -v /mnt:/var/www/html myos:httpd
从远端拉文件
rsync -av 用户名:文件目录 文件
docker 网络
理解DockerO
- 查看容器的内部网络地址ip addr,发现容器启动的时候会得到一个ethoGif262 ip地址,docker分配的!
原理
- 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术!
- 再次测试
我们发现这个容器带来网卡,都是一对对的
evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
正因为有这个特性,evth-pair充当一个桥粱,连接各种虚拟网络设备的
openstac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
结论: tomcat01和tomcat02是公用的一个路由器,dockerO。
所有的容器不指定网络的情况下,都是doFker0路由的,docker会给我们的容器分配一个默认的可用IP
小结
Docker使用的是Linux的桥接,宿主机中是一个Dokcer容器的网桥dockerO。
Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件!)
只要容器删除,对应网桥一对就没了!
- -link
思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?
#通过–link既可以解决了网络连通间题
[root@kuangshen /]# docker run -d -p --name tomcat03 --link tomcat02 tomcat
其实这个tomcat03就是在本地配置了tomcat02的配置
#查看hosts配置,在这里原理发现!
[roat@kuangshen/]# docker exec -it toncat03 cat /etc/hosts
127.0.0.1localhost
: :1 localhost ip6-1ocaThost ip6-1oopback
fe00: :0 ip6-1ocalnet
ff00: :0 ip6-mcastprefix
ff02::1 ip6-a1lnodes
ff02 : : 2 ip6-allrouters
172.18.0.3 tomcat02312857784
cd4172.18.0.4 5ca72d80ebb0
--link 就是我们在hosts配置中增加了一个172.18.0.3 tomcat02 312857784cd4
自定义网络
查看docker网络模型
docker network list
[ root@docker1 ~]# docker network ls
网络模式
bridge :桥接docker0(默认,自己床架也使用bridge 模式)
none :不配置网络
host :和宿主机共享网络
container:容器网络连通!(用的少!局限很大)
测试
#我们直接启动的命令--net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -p --name tomcat01 --net bridge tomcat
# docker0特点:默认,域名不能访间,--link可以打通连接!
#我们可以自定义一个网络!
--driver bridge
―-subnet 192.168.0.0/16
—-gateway 192.168.0.1
[ root(kuangshen /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
[root@kuangshen /]# docker network ls #查看一下
查看自己创建的网络
[ root@kuangshen /]#docker network inspect mynet
再创建一个tomcat02测试和tomcat01是否通
[root(@kuangshen /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
[ root@kuangshen /]#docker network inspect mynet #再看一下发现有两个容器
不使用--link也可以ping名字
[root@kuangshen /]# docker exec-it tomcat-net-01 ping tomcat-net-02 #通过名字ping也可以
我们白定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处︰
redis -不同的集群使用不同的网络,保证集群是安全和健康的
mysql -不同的集群使用不同的网络,保证集群是安全和健康的
测试打通mynet 和 tomcat01
[root@kuangshen/]# docker network connect mynet tomcat01
#连通之后就是将tomcato1放到了mynet网络下
#一个容器两个ip地址
#阿里云服务,公网ip和私网ip
[ root@kuangshen /]#docker network inspect mynet #查看下连通后的变化
创建虚拟交换机
[ root@docker1 ~]# docker network create --subnet=10.10.10.0/24 docker1
查看虚拟交换机详细信息
docker network inspect docker1
设置创建的网络为docker1
[root@docker1 ~]# docker run -it --network=docker1 myos :latest
ip a s docker0
brctl show docker0
客户端访问容器内的资源
默认容器可以访问外网,但外部网络的主机不可以访问容器内的资源
容器的特征是可以把宿主机变成对应的服务
一我们可以使用-p参数把容器端口和宿主机端口绑定
-p宿主机端口:容器端口
--例如把docker1 变成 httpd
docker run -itd -p 80:80 docker.io/myos:httpd
一例如把docker1 变成nginx
docker run -itd -p 80:80 docker.io/nginx:latest
实战︰部署Redis集群
创建redis网卡
[ root@kuangshen / ]# docker network create redis --subnet 172.38.0.0/16