Docker 基础
一、Docker的基本组成
镜像(Images)
- Tomcat镜像==》run ==》Tomcat01容器,通过这个镜像可以创建多个容器
容器(Container)
- Dccker利用容器技术,独立运行一个或者一组应用,通过镜像来创建启动,停止,删除
- 基本命令可以理解为一个简易的Linux系统
仓库(repository)
- 仓库就是存放镜像的地方,分为共有仓库和私有仓库
二、安装Docker
卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装包
yum -y install yum-utils
设置镜像仓库
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里云镜像仓库
安装Docker
yum makecache fast # 更新yum仓库的索引
yum -y install docker-ce docker-ce-clid.io
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING>d.io # 安装指定版本
systemctl strat docker && docker version
docker run hello-world # 测试
卸载Dcoker
yum remove docker-ce docker-ce-clid.io
rm -rf /var/lib/docker # docker 默认工作路径
rm -rf /var/lib/containerd
三、理解Docker
Docker run 后发生了什么
开始运行–docker会在本机寻找镜像–判断本机是否有此镜像
- yes – 使用这个镜像运行
- no – 去 docker hub 上下载 --下载镜像到本地–docker hub 找不到的话会返回错误
Docker 底层原理
- Docker 是一个 Client-Server 结构的系统,docker的守护进程运行在主机上,通过 socket 从客户端访问
- DockerServer 接收到 docker-client 的指令,就会执行这个命令
Docker为什么比 VM 快
- 因为 docker 有着比虚拟机更少的抽象层;
- VM 启动需要拉取操作系统,分钟级;Docker 容器启动是利用宿主机的操作系统,秒级启动
四、Docker 命令
镜像命令
docker images # 查看所有本地的主机上的镜像 -a 列出所有镜像 -q 只显示镜像的 id
docker search # 搜索镜像 --filter=STARS=3000 (通过收藏来过滤)
docker pull # 下载镜像 docker pull 镜像名:[:tag] 不写tag就是默认的 latest
docker rmi # 删除镜像 -f 镜像id -f $(docker images -aq) 删除全部容器
容器命令
docker pull 镜像
docker run [可选参数] images # docker run -it centos /bin/bash
# --name=“NAME” 容器的名字 MySQL01 MySQL02 用来区分容器
# -d 后台方式运行
# -it 使用交互式运行,进入容器查看内容
# -p 指定容器的端口 -p 8080:8080
# -c 加入命令
docker ps # 查看当前正在运行的容器 -a 列出所有运行过的容器 -n=? 显示最近创建的容器 -q 只显示容器的编号
退出容器:
exit # 直接容器停止并退出
Curl + p + q # 退出后容器不停止
docker rm 容器id # -f $(docker ps -aq) 删除所有的容器
启动和停止容器的命令
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id
常用命令
docker logs # -f -t 显示所有的日志和时间戳
# docker logs -f -t --tail 10 centos 没有日志,可以写个shell脚本 run -c 加命令
docker inspect 容器id # 查看容器的元数据
docker top # 查看容器的进程信息
docker exec -it 容器id /bin/bash # 进入正在运行的容器
docker attach 容器id # 正在运行的命令行,而不是打开新的窗口
docker cp 容器id:路径 本地路径 # 将容器内的 可以使用 -v 卷的技术,实现自动同步
docker stats # 查看 docker 状态
五、练习
1、docker run -d --name nginx01 -p 3344:80 nginx
# docker search nginx docker pull nginx --> -d 后台运行 --name 启动的名称 -p 暴露的容器的端口
2、docker run -it --rm tomcat:9.0
# --rm 一般用来测试,用完即删
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 启动无法访问,因为 webapps 没有内容,阿里云镜像原因,默认最小的镜像,不必要的剔除,保证最小可运行的环境
3、docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动 es
# es 非常耗内存;需要暴露的端口很多;es 的数据一般要放到安全目录!挂载 --nat somenetwork
# es 启动后 linux 卡顿: 加 -e 参数 -e ES_JAVA_OPTS="-Xms64m -Xmx512m"
4、Rancher / portainer docker的图形化界面管理工具,提供一个后台面板
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true protainer/protainer
# -v 挂载 里面的文件挂载到宿主机
六、Docker 镜像
docker 的镜像实际上是由一层一层的文件系统组成的,这种层级的文件系统 UFS(联合文件系统)
bootfs(boot file system)主要包含BootLoader和kernel,bootloader引导加载内;Docker 镜像的底层是 bootfs
rootfs(root file system)在 bootfs 之上,包含的就是典型的 linux 系统中 /dev、/proc、/etc、/bin 等标准文件和目录
rootfs就是各种不同操作系统的发行版,比如 Ubuntu …
- docker image inspect redis:latest # 查看镜像分层信息 (Layers – 层级)
七、如何提交自己的镜像
commit 镜像
docker commit 提交容器成为一个新的副本
docker commit -m=“提交的描述信息” -a=“作者” 容器id 目标镜像名称:[TAG]
# 命令
1、启动一个默认的 tomcat
2、tomcat 没有 webapps 应用,镜像原因,没有文件
3、cp -r webapps.dist webapps
4、docker commit -a="erik" -m="add webapps app" b1d2385ffd9e tomcat02:1.0
# 提交包含 webapps 的容器镜像
八、容器数据卷
什么是容器数据卷?
如果数据都在容器中,那么容器一删除数据就会丢失 ===== 希望数据可以持久化
mysql 容器删除,存储的数据会一起删除丢失 , mysql 的数据可以存储在本地
容器之间可以有个数据共享的技术,docker 容器中产生的数据,同步到本地
将容器内的目录,挂载在宿主机上,即 LINUX 上
使用数据卷
使用命令来挂载
docker run -it -v 主机目录:容器内目录
测试:
docker run -it -v /home/test:/home centos /bin/bash # 启动 centos 并挂载容器 /home 目录到宿主机的 /home/test 中
docker inspect 5f891a0afd0f # 查看容器详细信息
"Mounts": [
{
"Type": "bind",
"Source": "/home/test", # 宿主机地址
"Destination": "/home", # docker 容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
]
我们修改只需要在本地修改即可,容器内会自动同步!!
停止容器--宿主机修改文件--启动容器--容器内的数据依旧是同步的--只要容器还在
部署 MySQL 数据持久化
docker pull mysql:5.7
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 官方的测试 -e 配置密码
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# -d 后台运行 -p 暴露端口 -v 卷挂载 (可以挂载多个,比如配置文件目录和数据目录) -e 环境配置 --name 容器名字 navicat / sqlyog 测试连接 ,测试创建一个数据库查看数据
假设我们将容器删除,挂载在本地的数据卷依旧没有丢失,这就实现了数据持久化功能
具名挂载、匿名挂载
匿名挂载
-v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx
docker volumes ls
# 查看所有的挂载券的情况 名优指定的就是 匿名挂载
local 95aa41fddfa5f52116fa374a1006c5cd5dcd962264fd60f25dcb7889d50124b6
#这种就是匿名挂载,在 -v 只写了容器内的路径,没有写容器外的路径
具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 通过 -v 卷名:容器内路径
docker volume inspect juming-nginx
# 查看这个卷,对应的路径是docker容器内的卷,没有指定路径一般都在 /var/lib/docker/volumes
通过 具名挂载 可以方便的找到我们的一个卷
如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内的路径
# 匿名挂载
-v 卷名:容器内路径
# 具名挂载
-v /宿主机路径:容器内路径
# 指定路径挂载 ,可以通过 / 判断
通过 -v 容器内路径:ro rw 改变读写权限
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
# ro readonly 只读
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# rw readwrite 读写
数据卷容器
- 容器间的共享文件,是一个双向拷贝的机制,只要有容器在使用,就不会丢失,生命周期会一直持续到没有容器使用为止
但是一旦你持久化到本地,这个时候,本地的数据是不会删除的 - 第一个 父容器 -v 持久化到本地-宿主机
- 多个 MySQL 同步数据
–volumes-from
- 启动三个容器 ,使用自己写的 dockerfile 启动
FROM centos
VOLUMES ["volume01","volumes02"] # 匿名挂载
CMD echo "---done---"
CMD /bin/bash
docker build -f dockerfile1 -t erik/centos .
# -f dockerfile 文件名称 -t tag . 当前目录
docker run -it f9a52e45e703 /bin/bash
# 进入容器 ll 查看,会看到生成镜像的时候自动挂载的,数据卷目录,这个卷会和外部有一个同步的目录
docker inspect cc33ec4fcafd
# 查看卷挂载的路径
"Mounts": [
{
"Type": "volume",
"Name": "dc9c06d73049af5915f3045168942e87ded0c867e103ae144e0582bf4a1dfb4d",
"Source": "/var/lib/docker/volumes/dc9c06d73049af5915f3045168942e87ded0c867e103ae144e0582bf4a1dfb4d/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "cd3c37e958c12d43dca134840d7fa4df84fb6bb4f1bf2ea63d99caa49660ab39",
"Source": "/var/lib/docker/volumes/cd3c37e958c12d43dca134840d7fa4df84fb6bb4f1bf2ea63d99caa49660ab39/_data",
"Destination": "volumes02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
docker run -it --name docker01 erik/centos /bin/bash
docker run -it --name docker02 --volumes-from docker01 erik/centos /bin/bash
# docker01 创建的内容会同步到 docker02 中
docker run -it --name docker03 --volumes-from docker01 erik/centos /bin/bash
--volumes-from
# 只要通过他就可以实现容器间的数据共享
实现多个 MySQL 数据共享
docker run -d -p 3310:3306 -v /home/mysql/conf -v /home/mysql/data -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
九、Docker 网络
理解 docker0 网络
网络模式
bridge:(默认) – 在 docker0 上搭桥
none: 不配置网络
host: 和宿主机共享网络
container: 容器网络连通 (局限性比较大,用得少)
ip addr
# lo: 本机回环地址 eth0:内网地址 docker0: docker0 地址 ,容器的网桥,所有的网络接口都是虚拟的,效率高
测试
docker run -d -P --name tomcat01 tomcat
docker exec -it tomcat01 ip addr
# linux 能不能 ping 通容器内部 ?
- 原理:我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了 docker,就会有一个网卡 docker0
- 桥接模式 使用了 veth-pair 技术
veth-pair 技术
-- 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
-- 正因为这个特性,veth-pair 充当一个桥梁,连接各种虚拟网络设备
-- openstack、docker 容器之间的链接,OVS 的连接,都是使用 veth-pair 技术
容器内通过服务名去访问
- 启动参数 --link 即可以解决网络连通问题
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 --link tomcat01 tomcat
docker exec -it tomcat02 ping tomcat01
docker exec -it tomcat03 cat /etc/hosts
# hosts 配置中增加了 tomcat01 的映射
Docker0 问题: 不支持容器名连接访问
docker network --help
docker run -d -P --name tomcat01 --net bridge tomcat
# 启动命令中 默认参数 --net 桥接网络,docker0
docker0 特点:默认;域名不能访问, --link 可以打通
- 创建一个网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 创建一个 mynet 网络
- 启动容器放在自定义网络
docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcat
docker exec -it tomcat-net-01 ping tomcat-net-02
# 不使用 --link 也可以 ping 通
好处:
- redis == 不同集群使用不同的网络,保证集群的安全和稳定
- mysql == 不同集群使用不同的网络,保证集群的安全和稳定
- 网络打通 == docker0 和 自定义网络 连通
docker network connect --help
docker network connect mynet tomcat03
# 连通之后就是将 tomcat03 放置到 mynet 网络下,一个容器两个 IP 地址 !
docker network inspect mynet
# 查看创建好的网络
十、Dockerfile
步骤
DockerFile:构建文件,定义了一切步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务器
DockerFile 的指令
docker build -f dockerfile文件路径 -t 镜像名:[标签]
FROM # 基础镜像,一切从这里开始构建
MAINAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤: Tomcat 镜像,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPORT # 暴露端口的配置
CMD # 指定这个容器启东的时候要运行的命令--》只有最后一个会生效,可被代替
ENTRYPOINT # 指定这个容器启东的时候要运行的命令--》可以追加命令
ONBUILD # 当构建一个被继承的 DockerFile 这个时候就会运行 ONBUILD 指令,触发指令
COPY # 类似 ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量