文章
时间轴
标签
音乐室
友人帐
一刻时光
清单
留言板
相册
算法海洋
关于
Slcpの童话镇 🏰
写文章
Docker入门实战
原创
Docker
云原生
发布日期:
2022年01月22日
文章字数:
5.1k
阅读次数:
8595
阅读时长:
0小时0分0秒
## 前言 玩Docker没linux,怎么行? - vmware虚拟机安装教程 地址:[https://slcp.top 。](https://slcp.top/article/read/48) - 腾讯云学生机,2核4G三年(211RMB) 地址:[https://cloud.tencent.com/act/campus](https://cloud.tencent.com/act/campus) - 阿里云学生机,免费(以前一年,现在贼短) 地址:[https://developer.aliyun.com/plan/grow-up](https://developer.aliyun.com/plan/grow-up) - 华为云学生机 地址:[https://developer.huaweicloud.com/campus](https://developer.huaweicloud.com/campus?productType=KC1_2&timeType=1®ionType=1&domainItemData=) > 推荐先白嫖免费,再入手腾讯云,当然最好先考虑全面再选择最优入手。我在想这广告打的,rmb没到位,大厂面试机会总得给个吧。 ## 初识 > 三部曲:是什么、能干嘛、怎么玩 ### 是什么 - Docker 是一个开源的应用容器引擎 - 诞生于 2013 年初,基于 Go 语言实现, dotCloud 公司出品(后改名为Docker Inc) - Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上 - 容器是完全使用沙箱机制,相互隔离 - 容器性能开销极低 - Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版) > 官网话语 > > Docker的主要目标是`Build,Ship and Run Any App,Anywhere`,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到`一次镜像,处处运行`。 > > Linux容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用打成镜像,通过镜像成为运行在Docker容器上面的实例,而 Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。 一句话:`Docker就是一种容器技术,解决技术跨环境迁移的问题` #### 容器与虚拟机 **传统虚拟机技术** 虚拟机(virtual machine)就是带环境安装的一种解决方案。也就是说可以在一种操作系统里面运行另一种操作系统。 虚拟机的`缺点`: - 资源占用多 - 冗余步骤多 - 启动慢 **容器虚拟化技术** Linux容器(Linux Containers,缩写为 LXC),是与系统其他部分隔离开的一系列进程,从另一个镜像运行,并由该镜像提供支持进程所需的全部文件。容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。 Linux 容器不是模拟一个完整的操作系统而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。 ![容器与虚拟机](https://img-blog.csdnimg.cn/img_convert/40daa1f9aa38363bc9626a7f2b6ea416.png) > Docker 和传统虚拟化方式的不同之处: > > * 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程; > > * 容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。 > > * 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。 ### 能干什么 一次构建,随处运行 * 更快速的应用交付和部署 * 更便捷的升级和扩缩容 * 更简单的系统运维 * 更高效的计算资源利用 ### 去哪玩 官网:[https://www.docker.com/](https://www.docker.com/) 仓库:[https://hub.docker.com/](https://hub.docker.com/) ## 安装 #### 先决条件 - 运行64位CPU架构的计算机。 - 运行Linux 3.8 或更高版本内核。 #### 查看自己的内核 `uname`命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)。 ![image-20220222155017124](https://img-blog.csdnimg.cn/img_convert/36d7f86d32c407eadf525b23c23411b7.png) Ubuntu安装3.8内核 ```shell apt-get update ``` \# 升级所有包同时也升级软件和系统内核 ```shell yum -y update ``` ```shell yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine ``` ### 安装所需的软件包(支持devicemapper存储类型) ```shell yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 ``` ### 设置镜像的仓库 ```shell yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo ``` ### 设置yum源 ```shell # 国内源地址: # 阿里云 yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 清华大学源 yum-config-manager \ --add-repo \ https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo ``` ### 安装docker ```shell yum install docker-ce docker-ce-cli containerd.io ``` ### 启动docker ~~~shell systemctl start docker ~~~ ### 测试 ~~~shell docker -v docker version --查看详细信息 ~~~ ### 配置自己的阿里云镜像加速(强烈推荐) > 当你配置好后,如果你在pull镜像时可能出现如下错误,请配置自己专属的阿里云镜像加速。 ~~~shell 报错: 1 [Errno 14] curl#35 - TCP connection reset by peer 2 [Errno 12] curl#35 - Timeout ~~~ #### 注册 ... #### 登录阿里云开发平台 ![image-20220304145511338](https://img.slcp.top/image-20220304145511338.png) #### 进入控制台 ![image-20220304145608752](https://img.slcp.top/image-20220304145608752.png) #### 选择容器镜像服务器 ![image-20220304145658794](https://img.slcp.top/image-20220304145658794.png) #### 获取加速地址 ![image-20220304150825897](https://img.slcp.top/image-20220304150825897.png) ## 常用命令 ### 查看docker是否工作 ```shell docker info ``` ### 启动docker服务 ```shell systemctl start docker ``` ### 停止docker服务 ```shell systemctl stop docker ``` ### 重启docker服务 ```shell systemctl restart docker ``` ### 查看docker服务状态 ```shell systemctl status docker ``` ### 开机启动docker服务 ```shell systemctl enable docker ``` ### 查看镜像 - 查看本地所有的镜像 `docker images [OPTIONS]` `docker images –q` # 查看所用镜像的id ### 搜索镜像 - 从网络中查找需要的镜像 ```shell docker search [OPTIONS] 镜像名称 ``` `--limit 数量 指定查看数量` ### 拉取镜像 从Docker仓库下载镜像到本地,镜像名称格式为 名称:版本号,如果版本号不指定则是最新的版本。 如果不知道镜像版本,可以去docker hub 搜索对应镜像查看。 ```shell docker pull 镜像名称 ``` ### 删除镜像 删除本地镜像 `docker rmi [OPTIONS] 镜像id` # 删除指定本地镜像 `docker rmi `docker images -q`` # 删除所有本地镜像 `docker rmi $(docker images -q)` # 删除所有本地镜像 ```shell -f 强制删除 forced ``` ### 查看容器 `docker ps [OPTIONS]` # 查看正在运行的容器 `docker ps –a` # 查看所有容器,包括正在运行和停止的容器 ### 创建并启动容器 `docker run [OPTIONS] IMAGE [COMMAND] [ARG...]`新建+启动容器 OPTIONS说明(常用):有些是一个减号,有些是两个减号 `--name`="容器新名字" 为容器指定一个名称; `-d`: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行); `-i`:以交互模式运行容器,通常与 -t 同时使用; `-t`:为容器重新分配一个伪输入终端,通常与 -i 同时使用; 也即启动交互式容器(前台有伪终端,等待交互); `-P`: 随机端口映射,大写P `-p`: 指定端口映射,小写p `ctrl + p +q `退出容器,不关闭容器 `exit` 退出并关闭容器 ### 进入正在运行的容器并以命令行交互 ```shell docker exec -it 容器ID bashShell docker attach 容器ID ``` ***上述两个区别*** attach 直接进入容器启动命令的终端,不会启动新的进程 用exit退出,会导致容器的停止。 exec 是在容器中打开新的终端,并且可以启动新的进程 用exit退出,不会导致容器的停止。 ### 图解 ![img](https://img-blog.csdnimg.cn/img_convert/aa5ba231ee34a47197128007b9e9b024.png) ~~~shell attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像 build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像 commit Create a new image from a container changes # 提交当前容器为新的镜像 cp Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中 create Create a new container # 创建一个新的容器,同 run,但不启动容器 diff Inspect changes on a container's filesystem # 查看 docker 容器变化 events Get real time events from the server # 从 docker 服务获取容器实时事件 exec Run a command in an existing container # 在已存在的容器上运行命令 export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ] history Show the history of an image # 展示一个镜像形成历史 images List images # 列出系统当前镜像 import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export] info Display system-wide information # 显示系统相关信息 inspect Return low-level information on a container # 查看容器详细信息 kill Kill a running container # kill 指定 docker 容器 load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save] login Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器 logout Log out from a Docker registry server # 从当前 Docker registry 退出 logs Fetch the logs of a container # 输出当前容器日志信息 port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口 pause Pause all processes within a container # 暂停容器 ps List containers # 列出容器列表 pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或者库镜像 push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器 restart Restart a running container # 重启运行的容器 rm Remove one or more containers # 移除一个或者多个容器 rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除] run Run a command in a new container # 创建一个新的容器并运行一个命令 save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load] search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像 start Start a stopped containers # 启动容器 stop Stop a running containers # 停止容器 tag Tag an image into a repository # 给源中镜像打标签 top Lookup the running processes of a container # 查看容器中运行的进程信息 unpause Unpause a paused container # 取消暂停容器 version Show the docker version information # 查看 docker 版本号 wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值 ~~~ ## Docker镜像 思考: - Docker 镜像本质是什么? 是一个分层文件系统 - Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G? Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层 - Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB? 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB ### 是什么 是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。 只有通过这个镜像文件才能生成Docker容器实例`类似Java中new出来一个对象`。 **分层镜像** 以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载 ![image-20220307090543833](https://img.slcp.top/image-20220307090543833.png) ### Docker镜像加载原理 Docker的镜像实际上由一层一层的`文件系统`组成,这种层级的文件系统`UnionFS`。 #### bootfs(boot file system) bootfs主要包含`bootloader`和`kernel`, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,`在Docker镜像的最底层是引导文件系统bootfs`。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。 ![1592761590593](https://img.slcp.top/3050f3c816c10eb66585127d82bea736.png) #### rootfs (root file system) 在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。 ![image-20220307091137204](https://img.slcp.top/image-20220307091137204.png) #### UnionFS(联合文件系统) UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它`支持对文件系统的修改作为一次提交来一层层的叠加`,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。`镜像可以通过分层来进行继承`,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 ![img](https://img0.baidu.com/it/u=793564717,1037188676&fm=253&fmt=auto&app=138&f=JPEG?w=780&h=439) 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。 > 平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M? ![img](https://img.slcp.top/image-20220307091528897.png) 对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。 **Docker镜像层都是只读的,容器层是可写的** > 当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。 > 所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。 ![1592761605037](https://img-blog.csdnimg.cn/img_convert/71a449c082b19c790332d38f4be1335d.png) ### 镜像制作 > 标准:docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名] **容器转为镜像(极简)** 1.使用docker commit命令可以将容器保存为镜像。 命令形式:docker commit 容器名称 镜像名称 ```shell docker commit 381827f60f70 itheima_tomcat:1.0 ``` 2.使用docker save命令可以将已有镜像保存为tar 文件。 命令形式:docker save –o tar文件名 镜像名 ```shell docker save -o itheima_tomcat:1.0.tar ``` 3.使用docker load命令可以根据tar文件恢复为docker镜像。 命令形式:docker load -i tar文件名 ```shell # 加载恢复镜像 docker load -i itheima_tomcat.tar # 在镜像恢复之后,基于该镜像再次创建启动容器 docker run -di --name=new_tomcat -p 8080:8080 itheima_tomcat:1.0 ``` **注意:新的镜像制作后,原本容器中挂载的目录将失效, 索引一般在恢复镜像创建容器容器的时候需要重新挂载。** ### 小总结 Docker中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似Java继承于一个Base基础类,自己再按需扩展。 新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层 ![image-20220307092552842](https://img.slcp.top/image-20220307092552842.png) ## 本地镜像发布阿里云 ### 流程图 ![image-20220307105713332](https://img.slcp.top/image-20220307105713332.png) ### 镜像的生成方法 ~~~shell docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名] ~~~ ... ### 将本地镜像推送到阿里云 - 准备素材原型 ![image-20220307110312982](https://img.slcp.top/image-20220307110312982.png) - 阿里云开发平台 [https://promotion.aliyun.com/ntms/act/kubernetes.html](https://promotion.aliyun.com/ntms/act/kubernetes.html) ![image-20220307110739971](https://img.slcp.top/image-20220307110739971.png) - 创建仓库镜像 1.选择个人实例 ![image-20220307110955786](https://img.slcp.top/image-20220307110955786.png) 2. 命名空间 ![image-20220307111043303](https://img.slcp.top/image-20220307111043303.png) ![image-20220307111115202](https://img.slcp.top/image-20220307111115202.png) 3.仓库名称 ![image-20220307111439916](https://img.slcp.top/image-20220307111439916.png) 4.进入管理界面获得脚本 ![image-20220307111525860](https://img.slcp.top/image-20220307111525860.png) 5.将镜像推送到阿里云 `下面命令是博主自己本地的,你自己酌情处理,不要粘贴我的。` ![image-20220307111717245](https://img.slcp.top/image-20220307111717245.png) ~~~shell $ docker login --username=sun_**** registry.cn-hangzhou.aliyuncs.com $ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/zz-docker-test/test:[镜像版本号] $ docker push registry.cn-hangzhou.aliyuncs.com/zz-docker-test/test:[镜像版本号] ~~~ ### 将阿里云上的镜像下载到本地 ```shell docker push registry.cn-hangzhou.aliyuncs.com/zz-docker-test/huaian:3.0 ``` ## 本地镜像发布私有云 ### 流程图 ![image-20220307112108113](https://img.slcp.top/image-20220307112108113.png) ### 是什么 - 官方Docker Hub地址:[https://hub.docker.com/](https://hub.docker.com/),中国大陆访问太慢了且准备被阿里云取代的趋势,不太主流。 - Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。 ```shell Docker Registry是官方提供的工具,可以用于构建私有镜像仓库 ``` ### 将本地镜像推送到私有云 1.下载镜像Docker Registry ```shell docker pull registry ``` ![image-20220307112916593](https://img.slcp.top/image-20220307112916593.png) 2.运行私有库Registry,相当于本地有个私有Docker hub ```shell #默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调 docker run -d -p 5000:5000 -v /slcpuse/myregistry/:/tmp/registry --privileged=true registry ``` ![image-20220307113048251](https://img.slcp.top/image-20220307113048251.png) 3.创建一个新镜像 ~ 4.curl验证私服库上有什么镜像 ```shell curl -XGET http://127.0.0.1:5000/v2/_catalog ``` ![image-20220307113219106](https://img.slcp.top/image-20220307113219106.png) 5.将新镜像huaian:3.0修改符合私服规范的Tag ```shell #按照公式: docker tag 镜像:Tag Host:Port/Repository:Tag #自己host主机IP地址,填写同学你们自己的,不要粘贴错误,O(∩_∩)O #使用命令 docker tag 将huaian:3.0 这个镜像修改为127.0.0.1:5000/huaian:3.0 docker tag huaian:3.0 127.0.0.1:5000/huaian:3.0 ``` 6.修改配置文件使之支持http ![image-20220307114114343](https://img.slcp.top/image-20220307114114343.png) > 别无脑照着复制,registry-mirrors 配置的是国内阿里提供的镜像加速地址,不用加速的话访问官网的会很慢。 > `2个配置中间有个逗号 ','别漏了`,这个配置是json格式的。 > `2个配置中间有个逗号 ','别漏了`,这个配置是json格式的。 > `2个配置中间有个逗号 ','别漏了`,这个配置是json格式的。 > > > > vim命令新增如下红色内容:vim /etc/docker/daemon.json > { > "registry-mirrors": ["https://k1jr5sxm.mirror.aliyuncs.com"]`,` > `"insecure-registries": ["127.0.0.1:5000"]` > } > > 上述理由:docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====> 修改完后如果不生效,建议重启docker 7.push推送到私服库 ~~~shell docker push 127.0.0.1:5000/huaian:3.0 ~~~ 8.curl验证私服库上有什么镜像2 ~~~shell curl -XGET http://127.0.0.1:5000/v2/_catalog ~~~ 9.pull到本地运行 ## 数据卷 思考: • Docker 容器删除后,在容器中产生的数据也会随之销毁 • Docker 容器和外部机器可以直接交换文件吗? • 容器之间想要进行数据交互? ![1592748818477](https://img-blog.csdnimg.cn/img_convert/f01091cbcc359dcd2e505634536ed744.png) ### 是什么 一句话:`有点类似Redis里面的aof和rdb文件` > 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性: > 卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷 * 数据卷是宿主机中的一个目录或文件 * 当容器目录和数据卷目录绑定后,对方的修改会立即同步 * 一个数据卷可以被多个容器同时挂载 * 一个容器也可以被挂载多个数据卷 ![1592748888266](https://img-blog.csdnimg.cn/img_convert/1b4307055ef850fc1b43d5692c84d788.png) ### 能干嘛 - 数据卷可在容器之间共享或重用数据 - 卷中的更改可以直接实时生效 - 数据卷中的更改不会包含在镜像的更新中 - 数据卷的生命周期一直持续到没有容器使用它为止 ### 配置数据卷 **创建启动容器时,使用 –v 参数 设置数据卷** ~~~shell docker run -it --privileged=true –v /宿主机绝对路径目录:/容器内目录 镜像名 ~~~ **注意事项:** - 目录必须是绝对路径 - 如果目录不存在,会自动创建 - 一个容器可以挂载多个数据卷 - 一个数据卷也可以被多个容器挂载 - 两个容器可以挂载同一个容器 **大坑** 容器卷记得加`--privileged=true` > Docker挂载主机目录访问如果出现cannot open directory .: Permission denied > 解决办法:在挂载目录后多加一个--privileged=true参数即可 > > 如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为, > 在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即 > 使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。 在宿主机中实现与容器目录的挂载: 在c1容器中的root目录下就可以看到data_container文件夹:如下图 ![image-20220307093206465](https://img.slcp.top/image-20220307093206465.png) 同时我们我们回到宿主机中,可以在data文件夹下创建一个文件itcast.txt ,可以发现在容器中也会生成itcast.txt文件:如下图 ![image-20220307093743322](https://img.slcp.top/image-20220307093743322.png) ![image-20220307093442847](https://img.slcp.top/image-20220307093442847.png) - 数据卷的持久化: 当我们把c1容器删除后,宿主机中的数据卷依然存在。 所以当我们重新创建一个容器的同时依然可以挂载宿主机中的data文件夹,对应data里的数据依然同步到容器中。 - 一个容器可以挂载多个数据卷 ![image-20220307093650551](https://img.slcp.top/image-20220307093650551.png) 3. 多个容器可以挂载同一个数据卷 ![1592749838266](https://img-blog.csdnimg.cn/img_convert/84aa7ec6406489f6901e00142e0f289f.png) 分别创建两个容器,两个容器都挂载宿主机中data目录,当 修改c3容器的data目录c4会实现同步。 从而实现两个容器之间的交互。 ### 配置数据卷容器 **多容器进行数据交换** 1. 多个容器挂载同一个数据卷 2. 数据卷容器 ![1592753247374](https://img-blog.csdnimg.cn/img_convert/f43cf356430ea9bb912d0aa39a9548b9.png) **步骤:** 1.创建启动c3数据卷容器,使用 –v 参数 设置数据卷 ```shell docker run –it --name=c3 –v /volume centos:7 /bin/bash ``` 2.创建启动 c1 c2 容器,使用 –-volumes-from 参数 设置数据卷 ```shell docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bash docker run –it --name=c2 --volumes-from c3 centos:7 /bin/bash ``` ### 数据卷小结 - 数据卷概念 宿主机的一个目录或文件 - 数据卷作用 容器数据持久化 客户端和容器数据交换 容器间数据交换 - 数据卷容器 创建一个容器,挂载一个目录,让其他容器继承自该容器( --volume-from )。 通过简单方式实现数据卷配置 ## Docker复杂安装详说之MySQL **主从复制原理**——默认你懂 **主从搭建步骤** 1.新建主服务器容器实例3307 ```shell docker run -p 3307:3306 --name mysql-master \ -v /mysql/mydata/mysql-master/log:/var/log/mysql \ -v /mysql/mydata/mysql-master/data:/var/lib/mysql \ -v /mysql/mydata/mysql-master/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:5.7 ``` 2.进入/mysql/mydata/mysql-master/conf目录下新建my.conf vim my.conf ```shell [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 ``` **温馨提示**`针对mysql5.7` 3.修改完配置后重启master实例 ```shell docker restart mysql-master ``` 4.进入mysql-master容器 ~~~shell docker exec -it mysql-master /bin/bash mysql -uroot -proot ~~~ 5.master容器实例内创建数据同步用户 ~~~sql CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%'; ~~~ 6.新建从服务器容器实例3308 ~~~shell docker run -p 3308:3306 --name mysql-slave \ -v /mysql/mydata/mysql-slave/log:/var/log/mysql \ -v /mysql/mydata/mysql-slave/data:/var/lib/mysql \ -v /mysql/mydata/mysql-slave/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:5.7 ~~~ 7.进入/mysql/mydata/mysql-slave/conf目录下新建my.conf vim my.conf ~~~conf [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实例 ~~~shell docker restart mysql-slave ~~~ 9.在主数据库中查看主从同步状态 ~~~sql show master status; ~~~ 10.进入mysql-slave容器 ~~~shell docker exec -it mysql-master /bin/bash mysql -uroot -proot ~~~ 11.在数据库中配置主从复制 ~~~sql 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; ~~~ **参数说明** > master_host:主数据库的IP地址; > master_port:主数据库的运行端口; > master_user:在主数据库创建的用于同步数据的用户账号; > master_password:在主数据库创建的用于同步数据的用户密码; > master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数; > master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数; > master_connect_retry:连接失败重试的时间间隔,单位为秒。 12.在数据库中查看主从同步状态 ~~~sql show slave status \G; ~~~ ![image-20220307104420033](https://img.slcp.top/image-20220307104420033.png) 13.在从数据库中开启主从同步 ~~~sql start slave; ~~~ 14.查看从数据库状态发现已经同步 ![image-20220307104602707](https://img.slcp.top/image-20220307104602707.png) 15.主从复制测试 主建表,从查表 0k ## Docerfile Dockerfile其实就是一个文本文件,由一系列命令和参数构成,Docker可以读取Dockerfifile文件并根据Dockerfifile文件的描述来构建镜像。 ![1592763188913](https://img-blog.csdnimg.cn/img_convert/29471949ad940b40af82027a57534eb5.png) ### 是什么 * Dockerfile 是一个文本文件 * 包含了一条条的指令 * 每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像 * 对于开发人员:可以为开发团队提供一个完全一致的开发环境 * 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件 构建一个新的镜像开始工作了 * 对于运维人员:在部署时,可以实现应用的无缝移植 **概述** ![image-20220307095803665](https://img.slcp.top/image-20220307095803665.png) **官网** Docker网址:[https://docs.docker.com](https://docs.docker.com/engine/reference/builder) **构建三步骤** - 编写Dockerfile文件 - docker build命令构建镜像 - docker run 依镜像运行容器实例 ### Dockerfile构建过程解析 **基础认知** - 每条保留字指令都`必须为大写字母`且后面要跟随至少一个参数 - 指令按照从上到下,顺序执行 - #表示注释 - 每条指令都会创建一个新的镜像层并对镜像进行提交 **Docker执行Dockerfile的大致流程** - docker从基础镜像运行一个容器 - 执行一条指令并对容器作出修改 - 执行类似docker commit 的操作提交一个新的镜像层 - docker再基于刚提交的镜像运行一个新容器 - 执行dockerfile中的下一条指令直到所有指令都执行完成 ### 关键字 | 关键字 | 作用 | 备注 | | ----------- | ------------------------ | ------------------------------------------------------------ | | FROM | 指定父镜像 | 指定dockerfile基于哪个image构建 | | MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 | | LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 | | RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] | | CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"] | | ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 | | COPY | 复制文件 | build的时候复制文件到image中 | | ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 | | ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value | | ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 | | VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] | | EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp | | WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 | | USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 | | HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 | | ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 | | STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 | | SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell | ### 自定义镜像 1.要求 Centos7镜像具备vim+ifconfig+jdk8 JDK下载地址 官网:[https://www.oracle.com/java/technologies/downloads/#java8](https://www.oracle.com/java/technologies/downloads/#java8) 其他:[https://mirrors.yangxingzhen.com/jdk/](https://mirrors.yangxingzhen.com/jdk/) 百度网盘:[https://pan.baidu.com/s/1KF-W4UvRrQVoDNjv_5_Q0A?pwd=tnly](https://pan.baidu.com/s/1KF-W4UvRrQVoDNjv_5_Q0A?pwd=tnly) 2.编写 编写Dockerfile `大写字母D` ```yml FROM centos MAINTAINER slcp 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-8u221-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-8u221-linux-x64.tar.gz /usr/local/java/ #配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_221 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 ``` 3.构建 > docker build -t centosjava8:1.5 . 4.运行 > docker run -it centosjava8:1.5 /bin/bash ### 虚悬镜像 #### 是什么 创建名,标签都是<none>的镜像,俗称dangling image。 Dockerfile写一个~ ~~~shell 1 vim Dockerfile from ubuntu CMD echo 'action is success' 2 docker build . ~~~ ![image-20220307105249055](https://img.slcp.top/image-20220307105249055.png) ## Docker网络 ![image-20220223134949379](https://img-blog.csdnimg.cn/img_convert/a787f292ca37a225e41639d87e3f1b8b.png) 命令查看 ~~~shell docker network --help ~~~ > bridge模式:使用 --network bridge 指定,默认使用docker0 > > host模式:使用 --network host指定 > > none模式:使用 --network none指定 > > container模式:使用 --network container:NAME(或者容器ID) 指定 > > 自定义网络模式:通过`docker network create 名称`创建,默认bridge模式。 注意:**自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)** ## Docker微服务实战 ### 部署springboot项目 1.准备好微服务工程 myblog.jar yml ~~~yml server.port=6001 # ========================alibaba.druid相关配置===================== spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.url=jdbc:mysql://192.168.111.169:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.url=jdbc:mysql://mysql:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.druid.test-while-idle=false # ========================redis相关配置===================== spring.redis.database=0 #spring.redis.host=192.168.111.169 spring.redis.host=redis spring.redis.port=6379 spring.redis.password= spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 # ========================mybatis相关配置=================== mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.atguigu.docker.entities # ========================swagger===================== spring.swagger2.enabled=true ~~~ 2.编写Dockerfile,构建镜像 ~~~dockerfile # 基础镜像使用java FROM java:8 # 作者 MAINTAINER slcp # VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为myblog.jar ADD myblog.jar myblog.jar # 运行jar包 RUN bash -c 'touch /myblog.jar' ENTRYPOINT ["java","-jar","/myblog.jar"] #暴露6001端口作为微服务 EXPOSE 6001 ~~~ ~~~shell docker build -t myblog:1.0 ~~~ 3.编写docker-compose.yml文件 ~~~yml version: "3" services: microService: image: myblog:1.0 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: 'myblog' MYSQL_PASSWORD: '123456' 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: atguigu_net: ~~~ 4.执行docker-compose up 5.测试~ 6.关闭docker-compose stop ### 部署war项目 操作如上,废话就不多说了,直接上代码 百度网盘:[下载](https://pan.baidu.com/s/13exsiivMhGowNjgRKXprbg?pwd=4bya) ## Docker-Compose服务编排 ### 是什么 Docker-Compose是Docker官方的开源项目,负责实现docker容器集群的快速编排。 ### 能干嘛 通过一个文件,解决了容器与容器之间如何管理编排的问题。也就是一键部署,减少不必要过程,提高效率。 ### 去哪下 官网:https://docs.docker.com/compose/compose-file/compose-file-v3/ 下载:https://docs.docker.com/compose/install/ ### 核心概念 一文件,两要素 文件: * docker-compose.yml 要素: * 服务(service) 一个个应用容器实例 * 工程(project) 由一组关联的应用容器实例组成的一个完整业务单元,在文件中定义 ### 使用步骤 - 利用 Dockerfile 定义运行环境镜像 - 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务 - 运行 docker-compose up 启动应用,完成一键部署上线 ### Compose常用命令 ~~~shell 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 # 停止服务 ~~~ ## Docker平台架构图 从其架构和运行流程来看,Docker 是一个 C/S 模式的架构,后端是一个松耦合架构,众多模块各司其职。 Docker 运行的基本流程为: - 用户是使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者。 - Docker Daemon 作为 Docker 架构中的主体部分,首先提供 Docker Server 的功能使其可以接受 Docker Client 的请求。 - Docker Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 的形式的存在。 - Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,并通过镜像管理驱动 Graph driver将下载镜像以Graph的形式存储。 - 当需要为 Docker 创建网络环境时,通过网络管理驱动 Network driver 创建并配置 Docker 容器网络环境。 - 当需要限制 Docker 容器运行资源或执行用户指令等操作时,则通过 Execdriver 来完成。 - Libcontainer是一项独立的容器管理包,Network driver以及Exec driver都是通过Libcontainer来实现具体对容器进行的操作。 ![架构图](https://img-blog.csdnimg.cn/img_convert/061834108e6db9f439284b2f4a20d076.png) ## 终章 恭喜你,成功卷傻一堆人,你离架构师又进了一步~ 然后k8s走起...
您阅读这篇文章共耗时:
0小时16分34秒
文章链接:
https://www.slcp.top/article/read/47
版权声明:
本博客所有文章除特別声明外,均采用
CC BY 4.0
许可协议。转载请注明来源
Slcp
!
转载文章以及部分引用均为自己整理记录学习而用,若有侵权,请联系删除。
Docker
评论
Valine
Gitalk
目录
搜索
首页
前进
后退
刷新
申请友链
在线联系