文章目录
为什么要用docker
一款产品:
开发:开发环境 — 开发人员
上线:应用环境,应用配置 — 运维人员
传统方法:开发人员打包好应用程序,剩下的交给运维
问题:
- 环境不同,版本更新,端口冲突等导致服务不可用,这对于运维来说,考验很大
- 环境配置费时费力
现在方法:开发打包部署上线,一套流程做完
docker解决了上面的问题:
打包项目带上环境(镜像) -> docker仓库 -> 下载发布的镜像 -> 直接运行即可
docker核心思想:
隔离:打包装箱,每个容器时相互隔离的
- 优点:
- 使得容器之间不会相互影响
- 通过隔离机制,使得某个容器能使用的资源被限制,这样可以节省设备资源,使得设备资源被利用到极致
docker与虚拟机的联系与区别:
- 虚拟机:例如VMware,通过这个软件我们可以虚拟出来多台电脑,缺点是十分笨重
- docker:使用了容器技术,也是一种虚拟化技术,但是十分轻巧
假设需要使用一台linux机器
- VMware:导入linux镜像(一台电脑)。隔离:需要开启多个虚拟机
- docker:隔离:镜像(最核心的环境(约4M大小) + 项目需要的运行环境)
- 传统虚拟机:虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- docker:容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有我们虚拟的硬件,所以就轻便了
docker为什么比VM快:
docker有着比虚拟机更少的抽象层
docker利用的是宿主机的内核,vm需要的是Guest OS。所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免启动引导程序。
docker的好处:
- 应用更快速的交付和部署
- 更便捷的升级和扩缩容
- 更简单的系统运维
- 更高效的计算资源利用
docker安装
-
docker的基本组成:
- 客户端(client)
- 服务器(docker_host)
- 仓库(registry)
- 镜像(image):docker镜像就好比一个模板,可以通过这个模板来创建多个容器。
- 容器(Container):docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。相当于一个小型linux系统。
- 基本命令:启动,停止,删除
- 可以将这个容器理解为一个简易的linux系统
- 仓库(repository):存放镜像的地方。仓库分为公有仓库和私有仓库:
- docker hub(国外)
- 阿里云,华为云等
-
安装docker
-
环境准备
- linux基础
- ubuntu22.04
-
环境查看
uname -r #确定内核在3.0以上 cat /etc/os-release # 查看操作系统信息
-
安装
帮助文档:https://www.runoob.com/docker/ubuntu-docker-install.html
- 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
- 安装需要的包
sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
- 设置仓库
# 添加Docker的官方GPG密钥 curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 验证是否拥有带指纹的密钥 sudo apt-key fingerprint 0EBFCD88
# 设置稳定版仓库 sudo add-apt-repository \ "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \ $(lsb_release -cs) \ stable"
- 安装 Docker Engine-Community
sudo apt-get install docker-ce docker-ce-cli containerd.io
- 查看是否安装成功,运行以下hello-world
sudo docker run hello-world
- 查看一下下载的hello-world镜像
docker images
- 卸载docker
sudo apt-get purge docker-ce # 删除安装包 sudo rm -rf /var/lib/docker # 删除镜像、容器、配置文件等内容,
/var/lib/docker是docker默认工作路径
-
配置阿里云镜像加速
-
-
回顾hello-world镜像拉取过程
- docker在本机寻找镜像,判断是否有镜像,如果有则使用并运行。否则执行下一步
- 去docker hub上下载。如果没找到镜像,返回错误。如果找到了镜像,将镜像下载到本地
- 使用下载好的镜像,下次运行时就可以直接从本机找到该镜像了
docker工作原理
docker是一个client-server结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问
docker-server接收到docker-client的指令,就会执行这个命令,可能是启动一个容器,这个容器就可以看成是一个小的linux系统,在这个容器内可以运行一些服务,例如mysql(3306端口)
docker命令
-
帮助命令
docker version
显示docker版本信息docker info
显示docker的系统信息,包括镜像和容器的数量docker --help
帮助命令docker <命令> --help
查看特定命令的帮助信息
-
帮助文档的地址:https://docs.docker.com/reference/
-
镜像命令
docker images
查看所有镜像
docker search <镜像名称>
搜索镜像
docker pull <镜像名称>
下载镜像
docker pull mysql
等价于docker pull docker.io/library/mysql:latest
下载指定版本mysql:docker pull mysql:5.7
docker rmi --f <镜像名称/镜像id>
删除镜像,使用镜像id不需要全写上,只需要写几个前缀,能够与别的镜像区分开即可docker rmi --f <镜像id> <镜像id>..
批量删除镜像docker rmi -f $(docker images -aq)
docker images -aq会查出所有镜像的id,这样可以删除所有镜像
-
容器命令
说明:有了镜像才可以创建容器,linux,下载一个centos镜像来学习
docker pull centos
-
容器运行
docker run [可选参数] <image>
新建容器并启动
--name="NAME"
容器名称-d
后台方式运行,后台运行时必须要有一个前台进程,否则docker发现没有应用,就会自动停止。具体例如:
docker run -d centos -c "while true;do echo kuangshen;sleep 1;done"
# 这段命令循环运行了一个前端shell脚本,这样就使得docker不停止-it
使用交互方式运行,进入容器查看内容-p 主机端口:容器端口
指定主机端口和容器端口的映射-p 容器端口
指定容器端口-P
随机指定端口
-
查看正在运行的容器
docker ps
查看正在运行的dockerdocker ps -a
查看正在+曾经运行的docker
-
终止容器
exit
停止容器并退出ctrl + p + q
容器不停止退出
-
删除容器
docker rm <容器id>
删除容器,不能删除正在运行的容器,如果像删除,加-f参数docker rm $(docker ps -aq)
删除所有容器docker ps -a -q|xargs docker rm
删除所有容器
-
容器启停
docker start <容器id>
启动容器docker restart <容器id>
重启容器docker stop <容器id>
停止当前正在运行的容器docker kill <容器id>
强制停止当前容器
-
日志、进程、元数据的查看
docker logs -tf --tail 10 <容器id>
查看尾部10条日志docker top <容器id>
查看进程信息docker inspect <容器id>
查看容器元数据
-
进入正在运行的容器、拷贝命令
docker exec -it <容器id> /bin/bash
交互模式进入docker attach <容器id>
交互模式进入docker cp <容器id>:<文件路径> <主机路径>
从容器内拷贝文件到主机上
-
docker搭建练习
-
Docker 安装 Nginx
- 搜索镜像
docker search nginx
或者直接dockerhub上搜索 - 下载镜像
docker pull nginx
- 查看镜像
docker images
- 启动镜像
docker run -d --name nginx01 -p 3344:80 nginx
给这个容器起一个名:nginx01,外面端口设置为3344(可以进行公网访问),容器内端口设置为nginx默认端口80,这样在外面就可以通过3344端口访问到nginx - 测试镜像
curl localhost:3344
- 交互模式进入容器
docker exec -it nginx01 /bin/bash
- 找到nginx应用路径
whereis nginx
问题:每次需要修改nginx配置文件都需要进入容器内部,十分麻烦,如果可以在容器外部提供一个映射路径,使得能够修改容器内的文件。
-v 数据卷
- 搜索镜像
-
docker 安装 tomcat
- 直接用run自动下载镜像,启动容器
docker run -ti --rm tomcat:9.0
--rm参数表示该容器用完(stop)即删除,是用来测试的 - 正常启动容器
docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0
- 查看容器
docker ps
- 进入容器
docker exec -it tomcat01 /bin/bash
- 终止容器
docker stop tomcat01
- 删除容器
docker rm tomcat01
- 直接用run自动下载镜像,启动容器
-
docker 部署 es + kibana
问题:
- es 暴露的端口很多
- es 十分耗内存
- es 的数据一般需要放置到安全目录!挂载
- 去dockerhub搜索elastic镜像
- 下载镜像,启动容器
docker network create somenetwork
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
- 查看容器cpu状态
docker stats
- 下载kibana镜像并运行,思考两个容器如何通信
docker可视化
-
portainer:docker图形化界面管理工具!提供一个后台面板供我们操作
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:
localhost:8088
默认用户名:admin
,设置密码:XXX
,选择local,connect
-
Rancher
docker镜像
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
-
如何得到镜像
- 远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
-
核心思想:层级文件系统Union File System(UnionFS)
分层下载的好处在于:当下载一个新的镜像时,如果之前下载过该镜像中的某一层,那么就不用重复下载了,节省内存。 -
特点:
docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层。
-
commit镜像:
docker commit -m="提交的描述信息" -a="作者" <容器id> 目标镜像名:<tag>
docker images
查看提交的镜像
docker容器数据卷
- 问题:docker是将应用和环境打包成一个镜像,但是不考虑数据。如果数据都存放在容器中,那我们将容器删除,数据就会丢失
- 需求:数据可以持久化
- 解决方法:容器之间需要一个数据共享的技术。docker容器中产生的数据,同步到本地,这就是卷技术。
简单来说,卷技术就是目录的挂载,将容器内的目录挂载到主机上。举例:
方式1:使用命令来挂载:
docker run -it -v 主机目录:容器目录 <容器id>
docker inspect <容器id>
查看挂载情况,双向绑定,不管修改主机还是容器,都会同步。即使容器被停止了,也会同步
-
实战:同步mysql数据
运行容器:
docker run -d -p 3310:3306 -v /home/yonghu/ceshi:/etc/mysql/conf.d -v /home/yonghu/ceshidata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
实现多个挂载,配置文件挂载和数据挂载 -
具名挂载和匿名挂载
- 匿名挂载:
-v 容器路径:<权限>
- 具名挂载:
-v 卷名:容器路径:<权限>
- 指定路径挂载:
-v 主机路径:容器路径:<权限>
<权限>
可以设置为ro
只读、rw
读写。ro
权限是只能主机进行修改,容器无法修改了。
docker volume ls
将所有的卷都打印出来
docker volume inspect <卷名>
查看指定卷的细节
所有的docker容器内的卷,没有指定目录的情况下都是在
/var/lib/docker/volumes
目录下 - 匿名挂载:
方式2:使用DockerFile来挂载
DockerFile就是用来构建docker镜像的构建文件。其实就是一个命令脚本,通过这个脚本可以生成一个镜像。镜像是一层一层的,因此脚本是一个一个的命令,每个命令都是一层。
mkdir ceshi
pwd
vim dockerfile1
创建一个dockerfile文件
FROM centos:指定基础镜像
VOLUME [“volume01”,“volume02”]:通过volume进行挂载
CMD echo “------end------”:输出end
CMD /bin/bash:进入到/bin/bash中
docker build -f dockerfile1 -t test/centos .
当前目录下build镜像
docker images
docker run -it --name mycentos test/centos /bin/bash
ls -l
exit
docker inspect mycentos
查看卷挂载主机路径
-
多个mysql同步数据
docker run -it --name centos01 test/centos
创建父容器(数据卷容器)
docker run -it --name centos02 --volumes-from centos01 test/centos
--volumes-from同步两个容器即使删除父容器,数据仍然存在
DockerFile
DockerFile就是用来构建docker镜像的构建文件。其实就是一个命令脚本,通过这个脚本可以生成一个镜像。镜像是一层一层的,因此脚本是一个一个的命令,每个命令都是一层。
构建步骤:
- 编写一个 dockerfile 文件
- 构建一个镜像:
docker build -f <docker文件名> -t 镜像名 .
- 运行镜像:
docker run
- 发布镜像(dockerhub、阿里云镜像仓库):
docker push
-
DockerFile基础知识
- 每个保留关键字都必须是大写字母
- 执行从上到下顺序执行
- # 表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
-
DockerFile指令
- FROM:指定基础镜像。
示例:
FROM ubuntu:latest
- MAINTAINER:指定维护者信息。
示例:
MAINTAINER dj<123456@qq.com>
- RUN:在镜像中执行命令。
示例:
RUN apt-get update && apt-get install -y package
- COPY:将文件从构建上下文复制到镜像中。
示例:
COPY app.py /app/
- ADD:类似于 COPY 命令,但还支持远程URL和解压缩文件。
示例:
ADD http://example.com/file.tar.gz /data/
- WORKDIR:设置工作目录。
示例:
WORKDIR /app
- EXPOSE:声明容器在运行时监听的端口。
示例:
EXPOSE 8080
- ENV:设置环境变量。
示例:
ENV MY_ENV_VAR=value
- CMD:指定容器启动后要执行的命令。只有最后一个会生效,可被替代。
示例:
CMD ["python", "app.py"]
- ENTRYPOINT:将容器作为可执行程序运行,忽略 CMD 指令。
示例:
ENTRYPOINT ["python","app.py"]
- VOLUME:声明容器中的挂载点。
示例:
VOLUME /data
-
实战:构建自己的centos
-
编写dockerfile文件
vim dockerfile2
FROM centos MAINTAINER dj<123456@qq.com> ENV MYPATH=/usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "----end----" CMD /bin/bash
-
构建镜像
docker build -f dockerfile2 -t test/mycentos .
-
运行容器
docker run -it test/mycentos
-
查看镜像是如何制作的
docker history <容器id>
-
-
CMD和ENTRYPOINT的区别
CMD命令:
vim dockerfile3
FROM centos CMD ["ls","-a"]
docker build -f dockerfile3 -t test/dockerfile3 .
docker run -it test/dockerfile3
正常运行得到:
docker run -it test/dockerfile3 -l
后面加一个-l
参数,报错:
docker run -it test/dockerfile3 ls -al
,正常运行
ENTRYPOINT命令(追加命令):
vim dockerfile4
FROM centos ENTRYPOINT ["ls","-a"]
docker build -f dockerfile4 -t test/dockerfile4 .
docker run -it test/dockerfile4
正常运行得到:
docker run -it test/dockerfile4 -l
,正常运行:
-
实战:部署tomcat
bilibili视频 - 部署tomcat -
发布自己的镜像到dockerhub
- dockerhub注册账号
- 使用命令登录账号
docker login -u <用户名> -p <密码>
- 提交镜像
docker tag <镜像id> <镜像名>:<tag>
指定某个镜像id
,复制一个名为<镜像名>:<tag>
的新镜像
docker push <镜像名>或者<镜像id>:<tag>
docker全流程
Docker网络原理
- 理解docker0
docker0相当于网关。
问题:docker是如何处理容器网络访问的?
-
解决上述问题
-
运行一个tomcat容器
docker run -d -P --name tomcat01 tomcat
-
查看容器内部网络地址
docker exec -it tomcat01 ip addr
-
尝试ping容器
ping 172.17.0.2
可以ping通 -
再开启一个tomcat容器
docker run -d -P --name tomcat02 tomcat
-
tomcat01尝试ping tomcat02
docker exec -it tomcat01 ping 172.17.0.3
,可以ping通
-
运行
ip addr
,此时多了两对网卡
每启动一个docker容器,dockers就回给dockers容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0(桥接模式),使用的技术是veth-pair技术。
veth-pair:是一对虚拟设备接口,成对出现,一端连接协议,一段彼此相连。例如主机如果想和容器通信,那么主机和容器就会彼此相连,然后再连接协议。
桥接模式:在bridged模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。主机网卡和虚拟网卡的IP地址处于同一个网段,子网掩码、网关、DNS等参数都相同。这种方式简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡 绑定两个不同地址类似,实际上是将网卡设置为混杂模式,从而达到侦听多个IP的能力。在此种模式下,虚拟机内部的网卡(例如linux下的eth0)直接连到了物理网卡所在的网络上,可以想象为虚拟机和host机处于对等的地位,在网络关系上是平等的,没有谁在谁后面的问题。
NAT模式:相当于宿主机再构建一个局域网,虚拟机无法和本局域网中的其他真实主机进行通讯。只需要宿主机器能访问互联网,那么虚拟机就能上网,不需要再去配置IP地址,子网掩码,网关。虚拟机和主机能够互相ping通。
-
-
容器互联 link
- 新建一个容器tomcat03来link tomcat02
docker run -d -P --name tomcat03 --link tomcat02 tomcat
- 测试用容器名,看能否ping通
docker exec -it tomcat03 ping tomcat02
,可以ping通
docker exec -it tomcat02 ping tomcat03
,不可以ping通
docker exec -it tomcat03 cat /etc/hosts
,查看路由,发现tomcat03的路由中存放着tomcat02的ip映射
docker exec -it tomcat02 cat /etc/hosts
,查看路由,发现tomcat02的路由中没有tomcat03的ip映射
- 新建一个容器tomcat03来link tomcat02
-
自定义网络
- 查看网卡
docker network ls
bridge:桥接模式(自定义网络)
host:和宿主机共享网络
none:不配置网络
container:容器网络连通
- 自定义网络
(1)docker run -d -P --name tomcat01 tomcat
等价于docker run -d -P --name tomcat01 --net bridge tomcat
,默认运行容器使用桥接模式
(2)docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
(3)docker network ls
(4)docker network inspect mynet
(5)docker run -d -P --net mynet --name tomcat01 tomcat
,运行一个自己网络下的容器
(6)自定义网络无需使用link也可以使用容器名进行ping通
- 查看网卡
问题:不同网段的容器如何互联?
-
容器连通
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 --net mynet tomcat
docker network connect mynet tomcat01
dcoker exec -it tomcat01 ping tomcat02
,可以ping通,反过来也可以ping通
docker network inspect tomcat01
,观察网卡信息,发现tomcat01被写入
docker exec -it tomcat01 ip addr
,查看tomcat01网卡信息,发现多了一个IP地址
docker compose
-
docker compose 介绍
之前docker只能每个容器单个操作build,run等命令,现在可以使用docker compose批量处理,轻松高效的管理容器。
-
三步骤:
- Dockerfile保证项目在任何地方运行
- 定义服务,编写docker-compose.yml文件
- 启动项目,docker-compose up
- 问题:如果要部署一个web服务,我们要使用到redis、mysql、nginx…多个容器,一个一个去build,run非常麻烦
- 解决:docker compose
-
compose中重要概念:
- 服务services:容器,应用。(web,redis,mysql…)
- 项目project:一组关联的容器。例如:博客
-
-
docker compose 安装
sudo curl -L "https://hub.nuaa.cf/docker/compose/releases/download/2.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
,修改权限docker-compose --version
,查看是否安装成功
-
docker compose 使用
正常步骤:
- 准备好所有需要的依赖文件
- 写好DockerFile来构建web应用镜像
- 仓库拉取redis镜像
- run,构造两个容器
- 对两个容器做互通
docker-compose:
- 准备好所有需要的依赖文件
- 写好DockerFile来构建web应用镜像
- 写docker-compose.yml文件
- 一键部署
docker-compose up
-
命令:
docker-compose up
启动docker-compose down
或ctrl+c
停止
-
docker-compose.yml文件编写
共三层:版本、服务、其他配置
官方文档version: ' ' # 版本 service: # 服务 服务1(web): images: build: network: ... 服务2(redis): ... # 其他配置 volumes: networks: configs: secrets: