文章目录
docker的出现:
假如你使用一台笔记本,且你的开发环境具有特定的配置。你开发的应用依赖于你的配置还有一些配置文件。而其他开发人员所处的环境配置也不相同。此外,你所处的企业还将具有标准的测试和生产环境,且具有自身的配置和一系列的配置文件。你希望尽可能多地在本地模拟这些环境且尽可能不重新创建服务器环境。
那么,你要如何确保应用能在这些环境中运行且通过质量检测?并且在部署过程中不出现令人头疼的版本、配置问题,也无需重新编写代码和故障修复?
使用容器!docker之所以发展迅速,是因为它对此给出了一套标准的解决方案——系统平滑移植、容器虚拟化技术。
环境配置相当麻烦,换一台机器就要重新来一次,费力费时。很多人想到,能不能从根本上解决问题:“软件可以带环境安装”?也就是说安装的时候,把原始环境一模一样地复制过来。docker就是规定了环境的一致,保证迁移的时候打包、运行不走样。
docker包含了下述的技术。
- 镜像技术
打破“代码即应用”的观念。
从系统环境开始,自底向上打包应用
docker中符合“镜像即应用”
打包镜像时需要将运行文档、配置环境、运行环境、运行依赖包、操作系统发行版一起打包进镜像中。
docker的理念
docker的主要目标:“Build,Ship and Run any app,Anywhere”。通过对应用的封装、分发、部署、运行等生命周期的管理,使用户的app(web应用、数据库应用等等)及其运行环境能够做到 “一次镜像、处处运行”。
docker是基于Go语言实现的云开源项目,是基于Linux容器技术上发展起来的。将应用打包成镜像,通过镜像成为运行的docker容器实例。而docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
总结的说,docker是解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
docker容器与传统虚拟机比较
虚拟机是带环境安装的一种解决方案
传统虚拟技术基于安装在主操作系统上的虚拟机管理系统(如VMware、virtualbox等),创建虚拟机(虚拟出各种硬件),在虚拟机上安装从操作系统,在从操作系统上安装部署各种应用。
缺点:
资源占用多
冗余多
启动慢
Linux容器(Linux container,LXC)
Linux容器不是模拟一个完整的操作系统,而是对进程隔离。有了容器,就可以将软件运行所需的全部资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
docker容器是在操作系统层面实现虚拟化,直接复用本地主机的操作系统,而传统虚拟机是在硬件层面上实现虚拟化。与传统的虚拟机相比,docker的优势体现在启动速度快、占用体积小。
总结来说,
- 传统虚拟技术是虚拟出一套硬件之后,在其上运行一套完整操作系统,在该系统上再运行所需应用进程。
- 容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且没有进行硬件虚拟,因此,容器比传统虚拟机更轻便。
- 每个容器之间相互隔离,每个容器有自己的文件系统,容器之间进程不会互相影响,能区分计算资源。
docker的理念带来的优势
docker的理念: “一次镜像、处处运行”
- 更快速的应用交付和部署
传统的应用开发完成后,需要提供一对安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置之后才能运行;
docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可。应用安装配置在镜像里已经内置好,大大节省了部署配置和测试验证时间 - 更便捷的升级和扩缩容
随着微服务架构和docker的发展,大量的应用会通过微服务的方式架构,应用的开发构建将变成搭乐高积木一样,每个docker容器就变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容由原来的小时级变成分钟级甚至秒级。 - 更简单的系统运维
应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的bug。当程序出现异常时,也可以通过测试环境的相同容器机型快速定位和修复。 - 更高效的计算资源利用
docker是内核级虚拟化,不像传统的虚拟化技术需要额外的Hypervisor支持,一台虚拟机上可以运行多个容器实例,可大大提高物理服务器的CPU和内存利用率。
关于docker的优势,在该文章:https://developer.aliyun.com/article/982521
中看到了更好理解的阐述。以下是描述:
1 、 简化程序
Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化 。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的 任务,在Docker容器的处理下,只需要数秒就能完成。
2 、 避免选择恐惧症
如果你有选择恐惧症,还是资深患者。Docker 帮你 打包你的纠结!
比如 Docker 镜像;Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。 比如 Web 应用、后台应用、数据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。
3 、 节省开支
一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。
4 、 持续交付和部署
对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署(Continuous Delivery/Deployment) 系统进行自动部署。 而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像
5 、 更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
docker的应用场景
docker借鉴了标准集装箱的概念。标准集装箱货物运往世界各地,docker将这个模型运用到自己的设计中,唯一不同的是:集装箱运输货物,而docker运输软件。
产生出开发/运维(DevOps)新一代开发工程师。
why docker
更轻量:基于容器的虚拟化,仅包含业务运行所需的runtime环境,centosOS/Ubuntu基础镜像进170M;宿主机可部署100-1000个容器
更高效:无操作系统虚拟化开销
更敏捷、更灵活
docker的三件套
- 镜像(image)
docker镜像文件类似于Java中的类模板
docker镜像就是一个只读的模板。镜像可以用来创建docker容器,一个镜像可以创建很多容器。它也相当于一个root文件系统。比如官方镜像centos:7就包含了完整的一套centos:7最小系统的root文件系统。相当于容器的“源代码” - 容器(container)
docker容器实例,类似于Java中new出来的类的实例对象
从面向对象角度理解:
docker利用容器独立运行一个或一组应用,应用程序或服务运行在容器中。容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像Java中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
从镜像容器角度理解:
可以把容器看作是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用容器 - 仓库(repository)
是集中存放镜像文件的地方
分为公开仓库和私有仓库两种形式
最大的公开仓库是docker hub(https://hub.docker.com),存放了大量的镜像供用户下载
国内的公开仓库包括阿里云、网易云等
docker的工作原理(入门版)
下图有客户端、docker宿主机、docker仓库
客户端通过连接docker daemon(docker守护进程是一个后台服务线程),可以执行创建、拉取镜像、及运行容器操作。docker守护进程运行在主机上(物理机或者虚拟机)。客户端可以build镜像,并放在本地的docker守护进程中,之后通过该守护进程启动容器。客户端要运行容器时,docker守护进程先检查本地是否有该镜像,若有,就使用本地镜像构建一个一个的容器。若没有就从docker仓库上先拉取镜像。如果docker仓库上也没有镜像,就会报错显示镜像不存在。
Docker是一个client-server结构的系统,docker守护进程运行在主机(物理机或者虚拟机)上,然后通过socket连接从客户端访问。守护进程从客户端接收命令并管理运行在主机上的容器。容器,是一个运行时的环境,可以同集装箱类比。
docker的整体架构及工作原理(进阶版)
docker是一个client/server模式的架构,后端是松耦合架构,众多模板各司其职。
- 用户通过docker client与docker daemon建立通信,并将请求发送给后者;
- docker daemon作为docker架构的主体部分,首先提供docker server的功能使其可以接收docker client的请求;
- docker engine执行docker内部的一系列工作,每一项工作都是以一个job的形式存在;
- job的执行过程中,当需要容器镜像时,如果本地有,就使用本地镜像,否则就从docker仓库中下载镜像,并通过镜像管理驱动graph driver将下载镜像以graph的形式存储;
- 当需要为docker创建网络环境时,通过网络管理驱动network driver创建并配置docker容器网络环境;
- 当需要限制docker容器运行资源或执行用户指令等操作时,则通过执行器驱动exec driver来完成;
- libcontainer是一项独立的容器管理包,network driver以及exec driver都是通过libcontainer来实现具体对容器进行的操作。
上述最底层是根的文件系统,以层级概念划分。底层就是微小版的Linux系统文件。
docker的安装
- docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。
- docker实质是在已经运行的Linux下制造了一个隔离的文件环境,因此它的执行效率等同于所部署的Linux主机
- 因此,Docker必须部署在Linux内核的系统上。如果其他系统需要部署Docker就必须安装一个虚拟Linux环境
安装官方文档进行:
https://docs.docker.com/engine/install/centos/
其中下载stable repository时,不使用官方文档上的命令,使用阿里云提供的下载地址,
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
docker run命令干了什么事
为什么docker会比虚拟机快
- docker有着比虚拟机更少的抽象层
由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在cpu、内存利用率上docker将会在效率上更有优势。 - docker利用的是宿主机的内核,而不需要加载操作系统内核
当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免系统级的引导、寻址、加载操作系统内核返回等费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载操作系统,返回新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。
docker的常用命令
帮助启动类命令
启动docker: systemctl start docker
停止docker: systemctl stop docker
重启docker: systemctl restart docker
查看docker状态: systemctl status docker
开机启动: systemctl enable docker
查看docker概要信息: docker info
查看docker总体帮助文档: docker --help
查看docker命令帮助文档: docker 具体命令 --help
镜像命令
docker images 列出本地主机上的镜像
参数:
-a :列出本地所有的镜像(含历史映像层)
-q :只显示镜像ID
docker search 某个XXX镜像名字
docker search [OPTIONS] 镜像名字
参数:
--limit : 只列出N个镜像,默认25个
docker search --limit 5 redis 列出点赞数前5的redis镜像
docker pull 某个XXX镜像名字 下载镜像
写法一:
docker pull 镜像名字[:TAG]
写法二:
docker pull 镜像名字
没有TAG就是最新版
等价于 docker pull 镜像名字:latest
例如:docker pull ubuntu
docker system df 查看镜像/容器/数据卷所占的空间
docker rmi 某个XXX镜像名字ID 删除镜像
docker rmi -f 镜像ID 删除单个
docker rmi -f 镜像名1:TAG 镜像名2:TAG 删除多个
docker rmi -f $(docker images -qa) 删除全部
什么是虚悬镜像
仓库名、标签都是的镜像,俗称虚悬镜像dangling image
例如:
有镜像id,也有大小,但是仓库名和标签均为none
这种镜像没有用,建议删除
有时候镜像构建时会出现一些问题,导致构建出这种镜像。
容器命令
镜像是模板,容器是镜像的实例
有镜像才能创建容器,
新建并启动容器
新建+启动容器 :docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS说明(常用):有些是一个减号,有些是两个减号
--name="容器新名字" 为容器指定一个名称;如果不指定,系统随机分配
-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);
-i:以交互模式运行容器,通常与 -t 同时使用;(interactive,交互)
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;(tty,伪终端)
也即启动交互式容器(前台有伪终端,等待交互);
例如: docker run -it ubuntu /bin/bash
docker run -it ubuntu bash
表示使用Ubuntu镜像以交互模式创建一个容器实例,并在容器内执行/bin/bash(bash)命令
镜像后的/bin/bash命令,表示我们希望有个交互式shell
要退出交互,输入exit
-P: 随机端口映射,大写P
-p: 指定端口映射,小写p
列出当前所有正在运行的容器:docker ps [OPTIONS]
OPTIONS说明(常用):
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
退出容器:
两种方式:
一:exit——run进去容器,exit退出,容器停止
二:ctrl+p+q——run进去容器,ctrl+p+q退出,容器不停止
启动已停止运行的容器:
docker start 容器ID或者容器名
重启容器:
docker restart 容器ID或者容器名
停止容器:
docker stop 容器ID或者容器名
强制停止容器:
docker kill 容器ID或容器名
如果容器正在运行,状态为up,那么需要先stop再rm删除,或者使用命令docker rm -f 容器名称或容器id 强制删除。
一次性删除多个容器实例:
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
xargs表示上一个命令的输出结果,传给了xargs
【重要】启动守护式容器(后台服务器)
在大部分的场景下,我们希望 docker 的服务是在后台运行的,
这时可以通过 -d 指定容器的后台运行模式。
docker run -d 容器名
#使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
问题:然后docker ps -a 进行查看, 会发现容器已经退出
很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,
我们配置启动服务只需要启动响应的service即可。例如service nginx start
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,
这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.
所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行,
常见就是 -it 命令行模式,表示我还有交互操作,别中断。
以redis演示前后台启动:
前台交互式启动:
docker run -it redis:6.0.8
这时容易不小心关闭窗口,导致服务中断,因此更适用于后台守护石启动。
后台守护式启动:
docker run -d redis:6.0.8
查看容器日志:docker logs 容器ID
因为容器可以看作是简易的Linux环境+运行在其中的应用程序,所以也可以查看容器中的Linux负载情况
查看容器内运行的进程:docker top 容器ID
查看容器内部细节:docker inspect 容器ID
【重要】进入正在运行的容器并以命令行交互:
docker exec -it 容器ID /bin/bash
或者使用:
docker attach 容器ID
-
使用exec -it 与attach的区别:
使用exec -it 重新进入容器原理是,在容器中打开新的终端,并且可以启动新的进程用exit 或者用ctrl+p+q退出,不会导致容器的停止。
使用attach 会直接进入容器启动命令的终端,不会启动新的进程
用exit退出,会导致容器的停止。 -
推荐使用 docker exec -it 命令,因为退出容器终端,不会导致容器的停止。
把容器内文件备份到主机
只是拷贝部分文件:
docker cp 容器ID:容器内路径 目的主机路径
备份整个容器:
export 导出整个容器的内容作为一个tar归档文件[对应import命令]
docker export 容器ID > 文件名.tar
回复备份的归档文件:
cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
docker镜像
什么是镜像
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。
联合文件系统UnionFS
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。**Union 文件系统是 Docker 镜像的基础。**镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。(多层文件系统堆叠,对应多种子功能叠加,最终合成一个完整的文件系统,组成一个完整的大功能)
docker镜像加载原理
(可以把容器看作是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用容器)
- docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就叫联合文件系统UnionFS。
- bootfs(boot file system,引导文件系统)主要包含bootloader(boot加载器)和kernel(Linux内核),bootloader主要是引导加载kernel。 Linux刚启动时会加载bootfs文件系统, 在Docker镜像的最底层是引导文件系统bootfs。 这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
- 由bootfs启动完Linux内核之后,就得到了一个简易版的Linux环境。
- rootfs (root file system) ,运行在bootfs之上,包含典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??
因为docker只需要最简易的环境,即bootfs和rootfs。
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用宿主机Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
为什么docker镜像要采用分层结构?
- 镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
Docker镜像层都是只读的,容器层是可写的
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
镜像层作为rootfs,是堆叠好的。
docker commit
docker commit提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 需要创建镜像的容器ID 要创建的目标镜像名:[标签名]
例如基于从docker hub上下载的Ubuntu镜像,运行Ubuntu镜像的一个容器实例:
docker run -it ubuntu /bin/bash
在创建的容器实例中,(例如容器id为abc),看到没有vim命令,
运行如下两个命令安装vim:
apt-get update
apt-get-y intall vim
能查看到容器abc中有vim命令
然后,将abc容器commit成一个新的镜像:
docker commit -m “add vim” -a “wam” abc reg.westos.org/myubuntu:1.3
commit完之后docker images就能查看新创建的镜像,新创建的镜像比原下载的镜像大。
相当于原下载的镜像为base镜像,通过编辑在base镜像上新添加了一层。之后可以基于原下载的Ubuntu镜像再继续叠加新的层,,也可以基于创建的myubuntu再叠加新的层,继续拓展镜像的功能。对base镜像进行功能的加强。
总结
Docker中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似Java继承于一个Base基础类,自己再按需扩展。
新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
docker 私有仓库
-
官方Docker Hub地址:https://hub.docker.com/,中国大陆访问太慢了且准备被阿里云取代的趋势,不太主流。
-
Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。
-
Docker Registry是官方提供的工具,可以用于构建私有镜像仓库。
向私有仓库registry上传镜像,流程:
-
下载镜像Docker Registry
docker pull registry -
运行私有库Registry,相当于本地有个私有Docker hub
docker run -d -p 5000:5000 -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry
默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调 -
演示案例:创建一个新镜像,ubuntu安装ifconfig命令
3.1 从Hub上下载ubuntu镜像到本地并成功运行
docker pull ubuntu
docker run -it ubuntu /bin/bash
原始的Ubuntu镜像是不带着ifconfig命令的
3.2 外网连通的情况下,安装ifconfig命令并测试通过
docker容器内执行上述两条命令:
apt-get update
apt-get install net-tools
3.3 安装完成后,commit我们自己的新镜像,在容器外执行下述命令
docker commit -m=“提交的描述信息” -a=“作者” 需要创建镜像的容器ID 要创建的目标镜像名:[标签名]
docker commit -m=“ifconfig cmd add” -a=“zzyy” a69d7c825c4f zzyyubuntu:1.2
3.4 启动我们的新镜像并和原来的对比
官网是默认下载的Ubuntu没有ifconfig命令
我们自己commit构建的新镜像,新增加了ifconfig功能,可以成功使用。 -
curl验证私服库上有什么镜像
curl -XGET http://localhost:5000/v2/_catalog
(模拟发送一个get请求)
可以看到,目前私服库没有任何镜像上传过。。。。。。 -
将新镜像zzyyubuntu:1.2修改符合私服规范的Tag
按照公式: docker tag 镜像:Tag Host:Port/Repository:Tag
docker tag zzyyubuntu:1.2 localhost:5000/zzyyubuntu:1.2 -
修改配置文件使之支持http
docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====> 修改完后如果不生效,建议重启docker
vim /etc/docker/daemon.json
{
“registry-mirrors”: [“阿里云镜像加速器地址”],
“insecure-registries”: [“localhost:5000”]
} -
push推送到私服库
docker push localhost:5000/zzyyubuntu:1.2 -
再次curl验证私服库上有什么镜像
能查看到私有仓库上有zzyyubuntu镜像 -
拉取镜像到本地并运行
docker pull localhost:5000/zzyyubuntu:1.2
docker run -it localhost:5000/zzyyubuntu:1.2 /bin/bash
容器内能使用 ifconfig 命令
docker容器数据卷
- - privileged=true参数的重要性
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个–privileged=true参数即可
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
因为在SELinux里面挂载目录被禁止掉了的,如果要开启,我们一般使用--privileged=true
命令,扩大容器的权限解决挂载目录没有权限的问题,也就是说,使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
docker run -v参数
- docker容器运行的应用程序,如果不小心stop容器,或者删除rm -f 容器,那么应用内的重要数据就丢失了。
通过数据卷的方式,能完成数据的持久化,对重要数据备份。 - docker数据卷通过将容器的目录和宿主机的目录做映射,将容器内的数据备份并持久化到宿主机目录
下述命令:
docker run -d -p 5000:5000 -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry
–privileged=true 授予容器内的root用户真正的root权限
-v 宿主机绝对路径:容器内路径
表示两个路径中内容共享和互通互联,
默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调
数据卷是什么
- 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
- 卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
总结的说,docker通过数据卷将docker容器内的数据保存进宿主机的磁盘中,以达到容器内数据的持久化和敏感数据备份的目的。即使容器意外被删除,数据还在。
运行一个带有容器卷存储功能的容器实例:
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
数据卷能干什么
- 将运用与运行的环境打包镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的
Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。
为了能保存数据在docker中使用卷。
特点:
1:数据卷可在容器之间共享或重用数据;
2:卷中的更改可以直接实时生效,即在容器中数据的更改可以实时同步到宿主机中;
docker cp命令和export命令需要手工备份,但是数据卷是自动且实时的备份;
3:数据卷中的更改不会包含在镜像的更新中;
4:数据卷的生命周期一直持续到没有容器使用它为止;
数据卷的案例
宿主机和容器之间映射添加容器卷
- 直接命令添加:
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
如果目录不存在,就会被自动创建 - 使用命令查看是否挂载成功:
docker inspect 容器ID
Source是宿主机路径
Destination是容器内路径 - 容器和宿主机之间数据共享
1)docker修改,主机能同步获得 ;
2)主机修改,docker能同步获得 ;
3)docker容器stop,主机修改,docker容器重启看数据是否同步。
docker容器stop,主机修改,docker容器重启之后数据能同步
读写规则映射添加说明
使用下述命令,设置容器内的路径为可读可写 (r w)
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
默认容器内权限为 r w
容器实例内部被限制,只能读取不能写 (r o):
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
此时如果宿主机写入内容,可以同步给容器内,容器可以读取到。只限制了容器内路径的权限,未限制主机。
卷的继承和共享
- 容器u1和宿主机之间进行数据卷映射:
docker run -it --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu
(这里最后加不加/bin/bash效果都一样,Ubuntu会自动返回一个终端)
创建文件:
touch u1data.txt - 宿主机在目录/mydocker/u能查看到容器u1内创建的文件u1data.txt,并继续创建文件:
touch hostdata.txt - 根据数据卷的继承公式:
docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
创建容器u2,u2继承容器u1的数据卷
docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu
容器u2内能查看到 u1data.txt和hostdata.txt
实现了宿主机和容器u1和容器u2之间数据共享 - 容器u2只是继承了容器u1 的数据卷挂载规则,两个容器还是相互独立的。如果父类容器u1 stop,对u2无影响,u2容器与宿主机仍然能共享数据。
- 在容器u1 stop期间,宿主机与u2共享了一些数据。如果重新docker start容器u1,u1上也能看到宿主机与u2共享的数据。u1重新上线,能立即同步到全部数据。
卷插件
上述是实现了单机版的宿主机与容器之间数据的共享同步。为了实现跨主机的数据同步,就需要使用卷插件。
https://blog.csdn.net/qq_43604376/article/details/124689430?spm=1001.2014.3001.5502
中展示了首先使用nfs文件系统实现两个主机之间的数据共享,然后使用卷插件convoy实现了两个主机之间不同容器的数据同步与共享。
docker常规安装简介
总体安装步骤
搜索镜像
拉取镜像
查看镜像
启动镜像——服务端口映射
停止容器
移除容器
安装tomcat
1.搜索tomcat镜像
docker search tomcat
2. 拉取tomcat镜像到本地
docker pull tomcat
3. docker images查看是否有拉取到的tomcat
docker images tomcat
4. 使用tomcat镜像创建容器实例(也叫运行镜像)
docker run -d -p 8080:8080 --name=t1 tomcat
5. 访问首页:
localhost:8080
首先确定有映射端口且关闭防火墙。
还有一个原因就是:最新版的tomcat对于首页的访问,发生了一些改变。
进入webapps目录,发现里面为空。因此访问会报404错误。将webapps目录删除:
把webapps.dist目录换成webapps
访问成功。
然后停止、删除 t1 容器。
docker stop t1
docker rm -f t1
上述版本的tomcat需要修改webapps之后才能使用,但是也可以使用免修改版的tomcat
下载镜像:
docker pull billygoo/tomcat8-jdk8
运行镜像:
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
可以直接localhost:8080访问。
安装mysql
- 搜索查找mysql镜像
docker search mysql - 从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.7
docker pull mysql:5.7 - 查看拉取的镜像
docker images mysql:5.6 - 运行mysql镜像:(后台守护式容器)
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
docker ps查看是否运行成功
进入容器:
docker exec -it 容器ID /bin/bash
然后:登录
mysql -uroot -p
输入密码,和之前MySQL增删改查的使用方式一样。同样可以用外部的数据库连接软件连接容器中运行的MySQL。
注意
docker 容器中运行的MySQL应用存在中文乱码问题。
向表中插入中文数据时,报错。
因为,没有修正docker上默认字符集编码。在MySQL容器中执行:
字符集编码仍是Latin1.
还有一个问题,就是MySQL容器创建时,没有挂载数据卷。如果该容器不小心被删除
docker rm -f 容器id,
那么其中的数据就没有了,损失巨大。
解决MySQL容器中文乱码和敏感数据迁移问题(实际应用)
-
运行镜像:
docker run -d -p 3306:3306 --privileged=true -v /zzyyuse/mysql/log:/var/log/mysql -v /zzyyuse/mysql/data:/var/lib/mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
–privileged=true:开启数据卷挂载权限
-v:挂载数据卷,将容器中MySQL的日志、数据和配置文件备份到主机
检查容器是否运行成功: docker ps -
宿主机上新建my.cnf【通过容器卷同步给mysql容器实例】
编写MySQL配置文件,解决中文乱码问题。
-
重启mysql容器
docker restart mysql
-
进入mysql容器:
docker exec -it mysql /bin/bash
然后连接mysql,输入密码:
mysql -uroot -p
SHOW VARIABLES LIKE 'character%';
查看到字符编码为utf8 -
测试
结论:docker安装完MySQL并run出容器后,建议请先修改完字符集编码后再新建mysql库-表-插数据
问题: 创建的应用容器被误删了,前提是该容器与宿主机做了数据卷映射。当重新创建容器,之前的数据还存在吗?
假如将当前容器实例删除,再重新来一次,之前建的db01实例还有吗?答案是有。
只要容器在创建时和宿主机映射数据卷,之后容器被删除,再次创建,仍然能保证之前的数据不丢失,数据的安全性得到加固。
安装redis
入门级:
- 从docker hub上(阿里云加速器)拉取redis镜像到本地标签为6.0.8
- 运行镜像:
docker run -d -p 6379:6379 redis:6.0.8
docker ps
docker exec -it 容器id /bin/bash
redis- cli
set k1 v1
get k1
实战:加容器数据卷+配置文件的指定运行
- 在CentOS宿主机下新建目录/app/redis(供接下来容器数据卷挂载)
mkdir -p /app/redis - 将一个redis.conf文件模板拷贝进/app/redis目录下
将准备好的redis.conf文件(可能是之前安装redis留下的配置文件)放进/app/redis目录下 - 宿主机的/app/redis目录下修改redis.conf文件
将daemonize yes注释起来或者 daemonize no设置,因为该配置和docker run中-d参数冲突,会导致容器一直启动失败
4. 使用redis6.0.8镜像创建容器(也叫运行镜像)
docker run -p 6379:6379 --name myr3 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
最后一个参数表示redis-server使用容器中/etc/redis/redis.conf配置文件启动redis,而容器中的该配置文件是由宿主机上修改后映射至容器的。
查看是否启动成功:docker ps
容器的启动原理图如下:
5. 进入redis容器:
`docker exec -it myr3 /bin/bash`
连接 redis-cli
set k1 v1
get k1
6. 证明docker启动使用了我们自己指定的配置文件
在修改配置文件之前,能切换至15号数据库:
![在这里插入图片描述](https://img-blog.csdnimg.cn/53e5ae597ac44f13bb2d3948ae988135.png)
在宿主机 vim /app/redis/redis.conf 修改配置文件:
将数据库的数量设为10
重启容器:
docker restart myr3
再重新进入容器 myr3:
发现不能切换至15号库,说明宿主机上的配置文件同步到了docker容器中。