我的博客地址:www.lss-coding.top
1. Docker 简介
Docker 它是一个开源应用容器引擎,允许开发者将其应用程序打包并依赖于可移植的镜像,然后发布到任何流行的镜像中 Linux或Windows虚拟化也可以在操作系统的机器上实现。容器完全采用沙箱机制,彼此之间没有接口。
Dcoker 是基于 Go 语言开发是一个开源项目。
官网:https://www.docker.com/
仓库:https://hub.docker.com/,相当于 GitHub ,镜像可以发布
1.1 Docker 为什么会出现?
在开发产品时,需要开发和推出两套环境,不同的环境需要不同的配置。
有两个角色:开发和运维。
问题:当我的开发人员开发产品时,他们可以在自己的电脑上运行。如果版本更新,服务器将不可用,这对运维人员来说非常麻烦。
环境配置很麻烦,每台机器都要部署环境(集群 Redis 、ES、Hadoop)等等,很费时费力。
发布项目的时候是为了 jar 但需要依靠一些环境(Rdis、MySQL、JDK 等),项目不能全部带环境安装包装。
假设在服务器配置应用环境之前 Redis、MySQL、JDK,配置非常麻烦,无法实现跨平台开发系统 Windows ,发布到 Linux
传统的开发中:开发人员打 jar 包,运维人员在线部署
现在:在线开发包装部署,完成一套流程。
假设开发一个 apk 应用
- java – apk – 发布(应用商店)-- 用户使用 apk – 可安装使用
- java – jar(环境)-- 带环境(镜像)的包装项目。-- (Docker仓库)-- 下载发布的镜像 – 可以直接操作。
Docker 解决上述问题。
Docker 集装箱的思想。
JRE – 多个应用端口冲突)-- 原来都是交叉的。
隔离:Docker 核心思想,包装箱,每个箱子都是相互隔离的,Docker 服务器可以通过隔离机制使用。
1.2 Docker 的历史
2010 年,几个做 IT 年轻人在美国成立了一家公司dotCloud”
这家公司开始做一些事情 pass 云计算服务,LXC 他们将自己的技术(容器化技术)命名为相关的容器技术 Docker,Docker 刚出生的时候,没有引起业界的注意,公司坚持不了。
所以我选择了2013年的开源 年 Docker 开源后,越来越多的人发现了它 Docker 火了之后,优点 Docker 每月更新一个版本。2014年 年 4 月 9 日,Docker1.0 发布。
在容器技术出现之前,我们都使用虚拟机技术。
虚拟机:在 windows 中装一个 vmware,我们可以通过这个软件虚拟一台或多台电脑,非常笨重。
虚拟机也属于虚拟化技术;Docker 容器技术也是一种虚拟化技术。
1.3 Docker 能干什么
计算机中有一个内核,一个运行所需的库,然后所有开发的软件都在计算机上运行。
虚拟机技术缺点:
- 资源占用很多
- 冗余步骤很多(每次使用都需要手动打开)
- 开启的客户端更多,启动非常慢
容器技术不是一个完整的模拟操作系统。
- 比较不同
虚拟机是一套运行完整操作系统的虚拟硬件,在该系统上安装和运行软件。
容器中的应用程序直接运行在宿主机的内容中。容器没有自己的核心或虚拟硬件,所以非常轻。每个容器相互隔离,每个容器都有自己的文件系统,不相互影响。
2. Docker 安装
2.1 Docker 的基本组成
- 镜像(image):
镜像就像一个模板,可以通过这个模板创建容器服务,假设有一个 tomcat 镜像,通过 run 方法运行,tomcat01 容器(提供服务器)可以通过此镜像创建多个容器(最终服务运行或项目运行在容器中)。
- 容器(container):
利用容器技术独立运行一组或一组应用,通过镜像创建,可以假设容器是简单的 Linux 系统
- 仓库(repository)
存放镜像的地方分为公共仓库和私人仓库
Docker Hub 在国外,阿里云、腾讯云等都有容器服务器
2.2 安装 Dcoker
- 环境准备
一台 Linux 系统服务器,CentOS 7
参考地址:https://docs.docker.com/engine/install/centos/
- 卸载旧版本
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
- 安装所需的安装包
sudo yum install -y yum-utils
- 设置镜像的仓库
# 国外的,非常慢 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 阿里云镜像安装地址 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 更新 yum 软件包索引 yum makecache fast
- 安装 docker 相关
sudo yum install docker-ce docker-ce-cli containerd.io yum install docker-ce-18.06.1.ce-3.el7 docker-ce-selinux-18.06.1.ce-3.el7 sudo yum install docker-ce-18.06.1.ce-3.el7 docker-ce-cli-18.06.1.ce-3.el7 containerd.io
- 启动 docker
systemctl start docker
- 使用
docker version
检查安装是否成功
- 测试 Hello,World
docker run hello-world
- 查看一下下载的 hello-world 镜像
docker images
- 卸载 docker
# 卸载依赖 yum remove docker-ce docker-ce-cli containerd.io # 删除运行环境 rm -rf /var/lib/docker /var/lib/docker //docker 的默认工作路径
2.3 Dcoker Run 的运行流程
Docker 是怎么工作的?
Docker 是一个 Client-Server 结构的系统,Docker 是守护进程运行在主机上,通过 Socket 从客户端访问,Docker Server 接收到 Docker-Client 的指令,就会执行这个命令。
Dcoker 为什么比 VM 快?
- Docker 有着比虚拟机更少的抽象层
- Dcoker 利用的是宿主机的内核,vm 需要的是 GuestOS
新建一个容器的时候,docker 不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载 GuestOS,是分钟级别的;docker 是利用宿主机的操作系统,省略了复杂的引导过程,是秒级的。
3. Docker 常用命令
3.1 帮助命令
docker version #显示 docker 的版本信息 docker info #显示 docker 的系统信息,包括镜像和容器数量 docker 命令 --help #帮助信息
帮助文档地址:https://docs.docker.com/reference/
3.2 镜像命令
查看所有本地的主机上的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 4 weeks ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的
标签 IMAGE ID 镜像的 id CREATED 镜像的创建时间 SIZE 镜像的大小 # 命令可选项 -a, --all 列出所有镜像 --digests Show digests -f, --filter filter Filter output based on conditions provided --format string Pretty-print images using a Go template --no-trunc Don't truncate output -q, --quiet 只显示镜像 id
-
搜索镜像
docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11587 [OK]
mariadb MariaDB Server is a high performing open sou… 4407 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 857 [OK]
# 可选项 ,过滤
--filter=STARS=3000 搜索出来的镜像就是 STARS 大于 3000 的
-
下载镜像
docker pull mysql [:tags] # 下载最新的 [:tags]指定下载
Using default tag: latest # 如果不写 tag,默认就是 latest 最新版
latest: Pulling from library/mysql
b380bbd43752: Pull complete # 分层下载,docker image 的核心,联合文件系统,这回下了这几个层,如果下面指定别的版本进行下载,如果有重复就不会下载
f23cbf2ecc5d: Pull complete
30cfc6c29c0a: Pull complete
b38609286cbe: Pull complete
8211d9e66cd6: Pull complete
2313f9eeca4a: Pull complete
7eb487d00da0: Pull complete
4d7421c8152e: Pull complete
77f3d8811a28: Pull complete
cce755338cba: Pull complete
69b753046b9f: Pull complete
b2e64b0ab53c: Pull complete
Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87 # 签名
Status: Downloaded newer image for mysql:latest
-
删除镜像,可以通过镜像 id 删除或者镜像名
docker rmi -f IMAGE ID # 删除指定的容器,也可以通过空格间隔删除多个
docker rmi -f $(docker images -aq) # 删除全部的容器
3.3 容器命令
注意:我们有了镜像才可以创建容器
测试使用,下载一个 CentOS 镜像
docker pull docker # 最新版的
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" 容器启动后的名字,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080
-p # ip:主机端口:容器端口
-p # 主机端口:映射到容器端口(常用)
-p # 容器端口
-P 随机指定端口
# 使用容器
# 启动并进入容器
docker run -it centos /bin/bash
# 从容器中退回到主机
exit 容器停止并退出
Ctrl + P + Q 容器不停止退出
# 列出所有运行中的容器
docker ps 列出正在运行的容器
docker ps -a 列出当前正在运行的容器 + 历史运行过的容器
-n=? 显示最近创建的容器
-q 只显示容器的编号
删除容器
docker rm 容器id # 删除指定id 的容器
docker rm -f $(docker ps -aq) # 删除所有的容器
启动和停止容器
docker start 容器id
docker restart 容 器id
docker stop 容器id
docker kill 容器id
3.4 其他常用命令
问题:当我们使用后台启动容器 centos 的时候docker run -d 镜像名
,使用 docker ps 发现 centos 停止了。这里是常见的一个问题,容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用就会自动停止;假设 nginx 容器启动后,发现自己没有提供服务,就会立刻停止,就没有程序了。
-
查看日志命令
docker logs -f -t --tail 5 容器 查看某一个容器的日志信息
-
查看容器中的进程信息
docker top 容器id
-
查看镜像的元数据
docker inspect
-
进入容器后开启一个新的终端,可以在里面操作(常用)
进入当前正在运行的容器
我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
进入容器正在执行的终端,不会启动新的进程。
-
从容器中拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
3.5 总结
attach # 当前 shell 下 attache 连接指定运行镜像
build # 通过 Dockerfile 定制镜像
commit # 提交当前容器为新的镜像
cp # 从容器中拷贝指定文件或者目录到宿主机上
create # 创建一个新的容器,同run,但不启动容器
diff #查看docker 容器变化
events # 从 docker 服务获取容器实时时间
exec # 在已存在的容器上运行命令
export # 导出容器的内容流作为一个 tar 归档文件[对应 import]
history # 展示一个镜像形成历史
images # 列出系统当前镜像
import # 从tar 包中的内容创建一个新的文件系统镜像[对应export]
info # 显示系统相关信息
inspect # 查看容器详细信息
kill # kill 指定 docker 容器
load # 从一个 tar 包中加载一个镜像[对应save]
login # 注册或者登录一个docker 源服务器
logout # 从当前Docker registry 退出
logs # 输出当前容器日志信息
port # 查看映射端口对应的容器内部源端口
pause # 暂定容器
ps # 列出容器列表
pull # 从docker 镜像源服务器拉取指定镜像或者库镜像
push # 推送指定镜像或者库镜像至docker 源服务器
restart # 重启运行的容器
rm # 移除一个或者多个容器
rmi # 移除一个或者多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可以继续 或 -f 强制删除]
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个tar包[对应 load]
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看docker 版本号
wait # 截取容器停止时间的退出状态值
4. Docker 安装使用
4.1 Docker 安装 Nginx
docker search
也可以在 docker.hub 上搜索,可以看到帮助文档
docker pull nginx
docker run -d --name nginx01 -p 3344:80 nginx
-d # 后台运行
-name # 容器名
-p # 宿主机端口:容器内部端口
4.2 Docker 安装 Tomcat
docker search tomcat
docker pull tomcat
docker run -d --name tomcat01 -p 8080:8080 tomcat
-
通过外网我们访问可以看到,结果是 404,因为 docker 下载下来的这个 tomcat 不是一个完整版的
我们使用命令进入容器查看
docker exec -it tomcat01 /bin/bash
whereis tomcat
进入到 tomcat 的目录下,我们看到 webapps 目录下是空的,因为部署的项目是在这个目录下的,而看到这个文件夹是空的,所以表示并没有进行任何的项目部署,所以会出现 404 页面的情况,这个原因是阿里云镜像的原因,在下载的时候默认是找的最小的镜像,所以它会把不必要的都剔除掉,保证最小可运行的环境。我们在 webapps 的同级目录下可以 看到一个 webapps.dist 目录,将这个目录的内容全部复制到 webapps 里面,然后重新访问就可以看到 tomcat 的首页内容了。
5. 可视化面板 portainer
Docker 图形化界面管理工具,提供一个后台面板供我们操作。
开启命令
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
下载完成之后我们可以通过浏览器访问 ip地址:8088 端口号
6. 镜像
镜像是什么:镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
所有的应用直接打包成 docker 镜像就可以直接运行。
获得镜像的方式:1. 从远程下载 2. 别人拷贝 3. 自己制作一个镜像DockerFile
6.1 UnionFS(联合文件系统)
在我们下载镜像的时候可以看到一层层的下载
UnionFS:Union 文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union 文件系统是 Dcoker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
6.2 Docker 镜像加载原理
docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system) 主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等
平时我们安装的虚拟机 CentOS 都是好几个 G,为什么 Docker 只有几百M?
对于一个精简的 OS,rootfs 可能很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就可以了。由此可见对于不同的 Linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发行版可以公用 bootfs。虚拟机是分钟级别的,容器是秒级。
6.3 镜像分层
在我们下载一个镜像的时候,终端输出的日志中可以明显的看到是一层一层的进行下载。
为什么 Docker 镜像要采用这种分层的结构呢?
最大的好处,就是可以实现资源的共享,比如有多个镜像都从相同的 Base 镜像构建过来,那么宿主机只需要在磁盘上保留一份 base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过命令:docker image inspect 镜像
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
假设基于 Unbuntu Linux 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
下图中镜像包含 3 个镜像层
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,下图中,每个镜像包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件
下图中是一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,因为最上层的文件 7 是文件 5 的更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。每种存储引擎都是基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW。
下图中是系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层。
6.4 Commit 镜像
docker commit 提交容器成为一个新的副本
docker commit -m="信息描述" -a="作者" 容器id 目标镜像名:[TAG]
在我们平常是使用中,下载一个镜像使用时需要对其进行一些修改,扩充,如果我们想要保存当前容器的状态,可以通过 commit 来提交,获得一个镜像,就好比 VM 虚拟机的快照功能。
- 在上面启动 tomcat 后 webapps 里面是没有东西的,所以访问 404
- 自己拷贝内容进 webapps
- 下面的命令进行提交为一个镜像,以后使用就可以通过我们修改过的镜像
docker commit -m="add webapps" -a="lss" xxxxxx tomcat001:1.0
7. 容器数据卷
7.1 什么是容器数据卷
docker 的理念就是将应用和环境打包成一个镜像,如果数据存储在容器中,那当我们的容器被删除了,数据也会丢失。我们需要对数据进行持久化,加入 MySQL 的容器中存储了数据,容器突然被误删除了,那数据就会丢失了,所以我们需要将数据存储在本地。
容器之间可以有多个数据共享的技术,Docker 容器中产生的数据同步到本地,这就是卷技术,目录的挂载,将我们容器内的目录挂载到 Linux 上。
7.2 通过命令挂载
docker run -it -v 主机目录:容器内目录
# 测试
docker run -it -v /home/test:/home centos /bin/bash
执行命令之后,无论是在镜像里面修改指定的目录还是在宿主机上修改指定的目录,另一方都能收到相应的变化信息,这种情况就是挂载成功了。
启动之后我们可以通过 docker inspect 容器id 来查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J9vy6dPh-1635640517571)(D:\notes\Docker\Docker 知识点总结.assets\image-20211027095035103.png)]
这里当我们停止运行容器之后,修改宿主机共享的文件的内容的,再次启动容器会发现数据也进行了相应的更新。双向的过程。
使用容器卷好处:绑定之后,我们修改本地的文件,在容器中也会进行同步修改。
7.3 安装 MySQL
- 搜索镜像
docker search mysql
- 拉取镜像
docker pull mysql:5.7
-
启动容器
这里应该注意,进入 mysql 需要有一个密码的配置
详细信息官网地址:https://registry.hub.docker.com/_/mysql
-d # 后台运行
-p # 端口映射 宿主机端口:容器端口
-v # 卷挂载
-e # 环境变量
--name # 容器名字
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
- 查看宿主机挂载的目录
-
使用 SQL_yog 连接MySQL
创建一个 test 数据库
- 查看
/home/mysql/data
目录下的内容
- 假设将容器删除,我们发现挂载在本地的数据卷依旧没有丢失,这就实现了容器的持久化功能
7.4 具名挂载和匿名挂载
7.4.1 匿名挂载
-v 容器内路径
docker run -d -p 80:80 -v /etc/nginx nginx
查看所有的 volume 情况
docker volume ls
这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径 ,没有写容器外的路径
7.4.2 具名挂载
-v 卷名:容器内路径
docker run -d -p 80:80 -v nginx01:/var/nginx nginx
7.4.3 卷挂载路径查看
所有的 docker 容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
,我们通过具名挂载可以方便的找到我们的一个卷,大多数情况使用
7.4.4 确定挂载方式
如何确定是具名挂载、匿名挂载、还是指定路径挂载?
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
- 读写权限
docker run -d -p 80:80 -v nginx01:/var/nginx:ro nginx
docker run -d -p 80:80 -v nginx01:/var/nginx:rw nginx
#通过 -v 容器内路径:ro rw 改变读写操作
ro readonly #只读 说明这个路径只能通过宿主机来操作,容器内部是无法操作的
rw readwrite #可读可写
#设置了这两个容器的权限,容器对我们挂载出来的内容就有限定了。
7.5 简单使用 DockerFile
DockerFile 就是用来构建 docker 镜像的构建文件,就是一个命令脚本
在 /home/docker-test-volume 目录下创建一个 dockerfile01 脚本文件,这个脚本可以生成镜像,里面的每一个命令都是一层
# 文件中的内容 这里面的每一个命令就是镜像的一层
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash
使用命令构建镜像
在 dockerfile01文件同级目录下
docker build -f dockerfile1 -t lss/centos .
使用命令 docker images
查看我们刚才构建的镜像
启动一下自己写的容器
docker run -it a542aa955836 /bin/bash
在容器中的 volume01 下创建一个 container.txt
文件
这个卷和外部一定有一个同步的目录,这里的是匿名挂载
使用命令 docker inspect 5c26b2ee40af
查看详细的信息
7.6 数据卷容器
多个容器实现数据的同步
- 启动 centos 镜像
docker run -it --name centos01 lss/centos
-
在启动一个 lss/centos 镜像
通过 --volumes-from 挂载到上一个启动的容器上实现数据的同步
--volumes-from # 相当于一个继承的关系
docker run -it --name centos02 --volumes-from centos01 lss/centos
-
在 centos01 的 volume01 文件夹下创建一个 test.java 文件
进入 centos02 后在 volume02 文件夹下也可以看到这个文件,实现了容器之间的数据同步。
加入一个 centos03 也挂载到 centos01上,然后删除掉 centos01 之后,这些共享的文件在 centos02 和 centos03 上并不会丢失的,这个文件都是双向拷贝存在的。
结论
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦将数据同步到本地,本地的数据是不会删除的。
8. DockerFile
Dockerfile 就是用来构建 docker 镜像的文件,通过它来生成一个镜像文件发布出去,可以理解为一个命令参数脚本。
8.1 DockerFile 介绍
查看官网:https://registry.hub.docker.com/
这个文件里面就是一些构建的命令
很多官网镜像都是基础包,很多功能是没有的,我们通常会自己搭建自己的镜像。
8.2 DockerFile 构建和指令
构建时需要很多的指令
8.2.1 基础
-
每个关键字(指令)都是必须是大写字母
-
执行从上到下顺序执行
-
( # ) 表示注释
-
每一个指令都会创建提交一个新的镜像层,并提交
-
编写一个 dockerfile 文件
-
docker build 构建成为一个镜像
-
docker run 运行镜像
-
docker push 发布镜像(DockerHub、阿里云镜像仓库)
DockerFile 是面向开发的,以后要想发布项目,做镜像,就要编写 DockerFile 文件。
步骤:开发、部署、运维
DockerFile :构建文件,定义了一切的步骤,源代码
DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行
Docker容器:容器就是镜像运行起来提供服务
8.2.2 DockerFile 指令
FROM # 基础镜像,一切从这里开始
MAINTAINER # 镜像是谁写的 姓名 + 邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat 镜像,这个tomcat 压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候需要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似 ADD ,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
8.3 DockerFile 构建镜像
Docker Hub 中 99% 镜像都是从这个基础镜像过来的: FROM scratch,然后配置需要的软件和配置来进行构建。
FROM centos
MAINTAINER lss<18764197362qq.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 文件名 -t 镜像名:[tag] .
docker build -f mydockerfile-centos -t centos:1.0 . # 注意后面这个 . 不能少
docker run -it mycentos:1.0 # 进入我们自己创构建的镜像
这里我们在 DockerFile 文件中有安装 net-tools 和 vim 的命令,所以在镜像中可以只用;官网的下载的原生的是不能使用的。
8.4 CMD 和 ENTRYPOINT 区别
- CMD:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
- ENTRYPOINT:指定这个容器启动的时候要运行的命令,可以追加命令
测试 CMD
- 创建一个文件 dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
- 构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .
- 运行镜像
docker run 037860b45b64
,在 run 的时候ls -a
命令生效
- 想要在这个镜像上追加一个命令
docker run 037860b45b64 -l
会出错
因为 cmd 的情况下,-l 替换了 CMD ["ls","-a"] 命令,-l 不是命令所以报错
这里可以使用 docker run 037860b45b64 ls -l
查看
测试 ENTRYPOINT
- 创建一个 dockerfile-entrypoint-test 文件
FROM centos
# 与 CMD 区别之处
ENTRYPOINT ["ls","-a"]
- 构建镜像
docker build -f dockerfile-entrypoint-test -t entrytest .
- 运行测试
docker run 368a821b1dcb
-
在执行的时候追加一个参数
docker run 368a821b1dcb -l
这里还是可以正常执行的,这里是直接拼接在 ENTRYPOINT 后面的
8.5 构建一个 tomcat 镜像
FROM centos
MAINTAINER lss<1876419736@qq.com>
COPY README.txt /readme.txt
ADD jdk-8u311-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.54.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.54
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.54/bin/logs/catalina.out
docker build -t dirtomcat . # 由于文件名是 Dockerfile ,所以不需要用 -f 参数去找文件
docker images
docker run -d -p 8080:8080 --name lss-tomcat -v /opt/build/tomcat/webapps:/usr/local/apache-tomcat-9.0.54/webapps/test -v /opt/build/tomcat/tomcat-logs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat
-
上面启动镜像的时候就已经做了卷的挂载,所以我们直接在本地编写项目就可以实现同步发布了
在
/opt/build/tomcat/webapps/
文件夹(上面 -v 挂载的)下创建一个 WEB-INF 文件夹,在这个文件夹下创建一个 web.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true">
</web-app>
在 tomcat 目录下创建一个 index.jsp 文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello Tomcat Docker!</h2>
<%
System.out.println("--- tomcat test ---");
%>
</body>
</html>
9. 发布镜像
9.1 发布到 DockerHub
-
登录
docker login -u lishisen -p ******
# 由于之间创建的镜像没有带版本号,所以提交的时候被拒绝了
# 增加一个 tag
docker tag 容器id lishisen/tomcat:1.0
# 然后提交就成功了
docker push lishisen/tomcat:1.0
可以看到,提交的时候也是按照镜像的层级来进行提交的。
9.2 发布到阿里云
-
这个命名空间可能就是一个很大的项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jg6a2qWo-1635640517631)(D:\notes\Docker\Docker 知识点总结.assets\image-20211028101215250.png)]
docker login --username=李时森111 registry.cn-beijing.aliyuncs.com
docker tag [ImageId] registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
10. Docker 网络
10.1 Docker0
问题:docker 是如何处理容器网络访问的?
有一个 tomcat 容器,一个 mysql 容器,那这两个容器之间是怎样通信的,是使用那个网络进行通信的?
查看能够 ping 同容器内的 ip 地址
docker run -d -P --name tomcat01 tomcat
-
在运行容器的时候加上 ip addr 命令
docker exec -it tomcat01 ip addr
# 注意这里下载的镜像如果这个命令不能用可能是镜像中没有这一个功能,可以上面安装过 net-tools 的 Dcokerfile 文件来自己重新构建一个镜像文件
启动后我们可以看到容器内部网络地址 ,容器启动的时候会得到一个 eth0@if33 的ip 地址,这是 docker 分配的。
我们使用 ping 命令是可以 ping 通这个 ip 地址的
当我们每启动一个 docker 容器的时候,docker 就会给 docker 容器分配一个 ip 地址;在宿主机上,只要我们安装了 docker ,就会有一个 docker0 的网卡,是使用的桥接模式,使用 veth-pair 技术。
当我们上面的容器启动之后,在宿主机上使用 ip addr 查看,可以看到有刚才启动的容器的 ip 的相关信息。
我们每启动一个容器就会多一个网卡,这个启动的容器带来的网卡都是一对一对出现,这就是 veth-pair 技术:就是一对虚拟设备接口,它们都是成对出现的,彼此相连的。
也就是因为有了这个特性,veth-pair 充当作为一个桥梁,连接这各种的虚拟网络设备,实现宿主机和容器之间的互联。
加入我们开启了两个容器 tomcat01、tomcat02 ,这两个容器之间也是可以通过ping 命令测试连通的,所以说容器之间也是可以相互通信的。
两个容器之间的通信并不是直接通信的,当安装 Docker 后会有一个 docker0 的网卡,这个就相当于是一个路由器,当 tomcat01 与 tomcat02 建立连接时,以 veth-pair 技术实现两个网卡之间的互联,然后路由器通过广播的方式或注册IP地址的方式进行发送连接。
tomcat01 和 tomcat02 是共用一个路由器 docker0。
所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用的 ip
Docker 使用的 Linux 的桥接,宿主机是一个 Docker 容器的网桥 docker0
Docker 中的所有网络接口都是虚拟的,因为 虚拟的接口转发效率高。
只要删除容器,对应的一对网桥就没了
10.2 link
场景:有一个微服务,database url = ip:,每一次用 docker 启动 MySQL 都会分配一个新的 ip ,如果 ip 变化了项目中的地址就会失效了,我们在项目不重启的情况下,数据库的 ip 地址换掉了,希望可以通过名字来访问这个容器,以此来解决这个问题。Docker 中使用 --link 来解决这个问题
分别查看两个 tomcat 的网卡 ip 地址
ping 相互的 ip 地址是可以通的
但是 ping 容器的名字是不能 ping 通的
-
再启动一个 tomcat03 容器,使用 --link 连接
docker run -d -p 8083:8080 --name tomcat03 --link tomcat01 tomcat
测试是否能通过容器名 ping 通
启动 tomcat03 可以 ping 通 tomcat01 通过容器名
**注意:**相反 tomcat01 ping tomcat03 就会失败,正向连接可以,反向连接可能不可以
docker network ls
docker inspect 上一条命令出来的id
可以看到为每一个启动的容器分配一个 ip
tomcat03 在本地配置了 tomcat02 的配置
通过查看 tomcat03 容器的 hosts 文件可以看到
docker exec -it tomcat03 vim /etc/hosts
# 可以看到 tomcat03 的 hosts 中有 ip 地址和容器名的映射关系
但是相反的是,在 tomcat01 的 hosts 文件中不能看到映射关系,所以 tomcat01 不能通过容器名 ping 通 tomcat03
--link
的操作其实就是在 hosts 配置配置了一个 ip 地址和 容器名 的映射关系,这种方式已经不再使用了。
docker0 问题:不支持容器名进行连接访问
10.3 自定义网络
通过命令 docker network ls
查看所有的 docker 网络
- bridge:桥接模式(默认)
- none:不配置网络
- host:主机模式,和服务器共享网络
- container:容器内网络连通(局限性大)
# 直接启动的命令,默认是有一个 --net bridge,这个就是 docker0
docker run -d -P --name tomcat01 [--net bridge] tomcat
# docker0 特点:默认的,域名不能访问,使用 --link 可以实现互联
# --driver bridge 网络模式,桥接,默认也是 bridge
# --subnet 192.168.0.0/16 子网,可以包含 255*255 个子网
# --gateway 192.168.0.1 网关
# mynet 自定义网络的名字
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
自己的网络就创建好了
docker run -d -p 8081:8080 --name tomcat01 --net mynet tomcat
docker run -d -p 8082:8080 --name tomcat02 --net mynet tomcat
## 使用 docker inspect mynet 查看详细信息
-
经过测试,通过 ip 地址和通过 容器名 都可以 ping 通
现在不适用 --link 也可以 ping 通了
我们自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐使用自定义的网络
redis:不同的集群使用不同的网络,保证集群是安全和健康的
mysql:不同的集群使用不同的网络,保证集群是安全和健康的
10.4 网络连通
在上面创建了一个自定义的网络,网段是 192.168.0.0,docker0 自带的网段上 172.18.0.0
两个网段的是不能连通的
在 docker0 上有两个 tomcat 容器,mynet 上有两个 tomcat 容器,这两个网段的容器也是不能 ping 通的,所以需要 docker0 上的容器连接到 mynet 上,实现两个不同网段的容器互联。
测试
tomcat01 容器连通 mynet 网络
docker network connect mynet tomcat01
docker inspect mynet # 查看详细信息
# 下图我们可以发现,连通之后直接把 tomcat01 放到了 mynet 下
# 官网:一个容器两个ip地址
docker exec -it tomcat01 ping tomcat-net-01
如果要跨网络操作别人,就需要使用 docker network connect 连通
11. 部署 Redis 集群
docker network create redis --subnet 172.38.0.0/16
for port in $(seq 1 6);
do
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >>/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
for port in $(seq 1 6);
do
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
done
docker exec -it redis-1 /bin/sh # 进到 redis-1 节点里面
# 执行命令创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
set a b
在集群中 set 一个值,显示的主机的 172.38.0.13 这个主机,然后使用命令 docker stop redis-3
停掉这个容器之后,在进入集群到 172.38.0.14 这个节点上,14 是 13 的从机,主机挂掉从机补上
docker 搭建 redis 集群完成。
12. Spring Boot 微服务打包 Docker 镜像
-
创建 Spring Boot 项目
Controller 请求返回 Hello,Docker
-
打包应用
把这个项目 package 打包成一个 jar 包,将这个 jar 包上传到 Linux 虚拟机上
- 编写 Dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
- 构建镜像
docker build -t demo .
- 发布运行
13. Docker Compose
13.1 介绍
官网:https://docs.docker.com/compose/
在上面的操作中,我们想要构建使用一个镜像的话需要进行:Dockerfile – build – run 手动操作,单个的容器。
如果说一个大的微服务项目中有成百个服务,并且的这些服务之间有着依赖关系,上面这种操作实现就会非常的繁琐。Docker Compose 就是用来进行轻松高校的管理容器,可以定义和运行多个容器。
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process:
- Define your app’s environment with a
Dockerfile
so it can be reproduced anywhere.- 创建 Dockerfile 保证项目在任何地方可以运行
- Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment.- 通过 docker-compose.yml 配置文件来定义服务
- 服务:容器、应用(web、mysql、redis …)
- Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using the docker-compose binary.- 启动项目
作用:批量容器编排
Compose 是 Docker 官方开源的项目,使用前需要进行安装。
Dokcerfile 可以让程序在任何地方运行,简化了运维的部署,假设有一个 web 服务,这个服务需要 多个容器:redis、mysql、nginx… 如果我们一个一个去 build 非常的麻烦。
可以写一个 Compose 批量把这些服务打包进来
version: "3.9" # optional since v1.27.0 services: web: 标签:
ydl连接器