相信大家再看了上一节的docker入门后能对docker有一定的理解了吧,至少怎么创建进入一个容器应该是没问题的了。但是docker的功能远不止上节介绍的那么简单,接下来我们继续讲讲docker的强大之处。
一. 镜像原理
老规矩,我们带着问题理解
问题一:镜像的本质是什么?
我们知道操作系统的组成部分很多块,其中docker用到的就是文件管理子系统,而linux中的文件系统由bootfs和rootfs两部分组成
- bootfs:包含bootloader(引导加载程序)和 kernel(内核)
- rootfs: root文件系统,包含的就是典型 Linux 系的/dev,/proc,/bin,/etc等标准目录和文件不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等
Docker镜像是由特殊的文件系统叠加而成最底端是 bootfs,并使用宿主机的bootfs 第二层是 root文件系统rootfs,称为base image然后再往上可以叠加其他的镜像文件统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。 一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。
当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器
问题二:为什么我们平时下的ubuntu镜像ios有2个多G,而一个普通的镜像只有几百M?
通过上面的讲解相信大家也知道了这个为什么了,是的,Centos的iso镜像文件包含bootfs和rootfs,而docker的unbuntu镜像复用操作系统的bootfs,只有rootfs和其他镜像层是需要下载的
问题三:为什么我们平时下载的tomcat只有70多M,然而tomcat的镜像高达500多M?
由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB
二. 数据卷
先来说说数据卷是什么,我们的window操作系统有一个叫共享盘的东西,还有linux上也有关于挂载的概念,其实数据卷和他们的作用是一样的,我们可以通过数据卷将宿主机和容器的文件关联起来,一方的内容发生改变另一方的内容也同步改变。
来,我们继续通过几个问题来了解一下数据卷的概念
问题一:Docker 容器和外部机器可以直接交换文件吗?
我们知道容器是一个个在宿主机中隔离开来的文件系统,所以我们的容器只能依靠宿主机通过命令来对容器进行操作,所以外部机器不可以直接和容器交换文件,但是外部机器可以通过宿主机对容器进行文件操作
问题二:Docker 容器删除后,在容器中产生的数据还在吗?
我们在删除容器后,在次通过镜像构建出来的容器是不保留原来修改的内容的,因为我们是通过镜像来构建容器的,镜像没改变,构建出来的镜像也还是原来的。
这个时候我们就会有人要说了,那我们构建的如mysql那岂不没有用,容器删除了就没了那岂不是太危险了,数据一点也不安全,说没就没
上个问题说到我们的宿主机是可以和容器进行数据交互的,那有没办法保存数据呢?
有的,在上一章中我们在启动tomcat的时候命令是不是加了个 -v 文件路径:文件路径 (当目录文件不存在时,系统会自动创建)
docker run -itd --name=c_tomcat -p 8081:8080 -v /root/tomcat:/usr/local/tomcat/webapps tomcat:9-jdk8
要是忘记了自己挂载的目录是什么,也可以通过
docker inspection
找到Mounts 里面有 Source 宿主机目录,Destination 容器目录
上一章我们最后在webapps不是创建了 /test/myIndex.html文件吗?走!我们去宿主机的/root/tomcat看看有什么变化
可以看到宿主机对应的目录也给我们创建了对应的文件
docker stop c_tomcat
docker rm c_tomcat
同时我们删除容器后发现宿主机的文件还能在的,这样我们可以通过挂载数据卷来保存我们的数据或者配置信息,非常好用~
好了,我们可以通过数据卷在宿主机和容器间进行数据交互,但是老这样太麻烦,像一些配置的,我们可以直接保存就好了。当然也是有办法的
docker commit c_tomcat mytomcat:1.0
docker save -o mytomcat.tar mytomcat:1.0
docker load –i mytomcat.tar
我们可以通过commit打包我们自己的镜像,然后用save -o 在当前目录生成一个压缩文件,这样我们就可以拿到一个可以传输的二进制文件了,当我们需要使用到自己的的镜像的时候,在对应的文件夹中使用load -i 生成我们自己的镜像
也可以使用dockerfile来生成镜像
Dockerfile 是一个文本文件包含了一条条的指令每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了
- 对于运维人员:在部署时,可以实现应用的无缝移植
我们简单编写一个dockerfile试试
#定义父镜像:
FROM centos:7
#定义作者信息:
MAINTAINER wangRL<wangRL@cm.cn>
#执行安装vim命令:
RUN yum install -y vim
#定义默认的工作目录:
WORKDIR /usr
#定义容器启动执行的命令:
CMD /bin/bash
然后通过命令
docker bulid –f dockerfile文件路径 –t 镜像名称:版本
三. 服务编排
我们在启动容器的时候,只有一两个容器要启动的时候还好,但我们一个项目可不仅仅就只有tomcat一个组件,想想平时一个项目可能用到nginx,redis,mysql,rabbitMQ,doubble,zookeeper。。。要是一个个启动那岂不要累死,
这个时候服务编排就发挥它的作用,首先我们先下载docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
下载完成后我们先准备一下环境
docker pull nginx
然后试着编写docker-compose的启动文件docker-compose.yml来编排一下nginx+tomcat
- 创建docker-compose目录
mkdir ~/docker-compose
cd ~/docker-compose
- 编写 docker-compose.yml 文件
version: '3'
services:
nginx:
image: nginx
ports:
- 80:80
links:
- app
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
app:
image: app
expose:
- "8080"
- 创建./nginx/conf.d目录
mkdir -p ./nginx/conf.d
- 在./nginx/conf.d目录下 编写wangRL.conf文件
server {
listen 80;
access_log off;
location / {
proxy_pass http://app:8080;
}
}
- 在~/docker-compose 目录下 使用docker-compose 启动容器
docker-compose up
- 测试访问
http://192.168.60.128:80/test/myIndex
四. 结束语
好了,docker的介绍就到这了,docker还是用的好还是对我们迁移项目很有帮助的,想想,要是我们维护好了一套环境并且打包了好docker镜像,那我们岂不是可以在多个地方复制出多套环境一模一样的系统,免去了环境搭建数据同步的烦恼。