一款产品从开发到上线,需要重复地配置环境和部署,对于开发和运维都不得不面对版本的迭代环境的兼容等问题,而docker镜像的设计,使得我们得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。Linux 容器技术的出现就解决了这样一个问题,而 docker 就是在它的基础上发展过来的。将应用运行在docker 容器上面,而 docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
docker是一种解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:1 资源占用多 2 冗余步骤多 3 启动慢
由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。 比较了 docker 和传统虚拟化方式的不同之处:传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
安装Docker的依赖库。
yum install -y yum-utils device-mapper-persistent-data lvm2
添加Docker CE的软件源信息。
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker CE。
yum makecache fast
yum -y install docker-ce
systemctl start docker
创建/etc/docker/daemo.json
,写入以下命令。
{
"registry-mirrors": ["https://kqh8****.mirror.aliyuncs.com"]
}
重新加载服务配置文件。
systemctl daemon-reload
重启Docker服务。
systemctl restart docker
拉取hello-world
容器
docker pull hello-world
查看执行以下命令查看是否拉取成功
docker images
执行hello-world容器
docekr run hello-world
若页面上打印Hello from Docker!
以及其他的一些提示语句说明docker正常安装
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。
docker version
docker info
docker --help
docker images [options]
options说明
执行结果说明
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
docker search [options] docker-name
options说明
docker pull docerk-name/docker-id[:tag]
[:tag]代表docker镜像的版本,不加则默认为最新版
docker rmi [-f] docker docker-id
加-f代表强制删除
docker rmi -f 镜像名1:TAG 镜像名2:TAG
docker rmi -f $(docker images -qa)
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS说明(常用):有些是一个减号,有些是两个减号
docker ps [OPTIONS]
OPTIONS说明(常用),什么都不加默认列表当前正在运行的docker容器:
docker start 容器ID或者容器名
docker restart 容器ID或者容器名
docker stop 容器ID或者容器名
docker kill 容器ID或者容器名
docker rm 容器ID
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
docker run -d 容器名
#使用镜像centos:latest以后台模式启动一个容器docker run -d centos
问题:然后docker ps -a 进行查看, 会发现容器已经退出很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行
docker logs -f -t --tail 容器ID
docker top 容器ID
docker inspect 容器ID
docker exec -it 容器ID bashShell
docker attach 容器ID
上述两个区别
docker cp 容器ID:容器内路径 目的主机路径
UnionFS(联合文件系统)
一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 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这里才200M??
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。
由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
最大的一个好处就是 - 共享资源 比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
docker commit 提交容器副本使之成为一个新的镜像
docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
下载tomcat镜像到本地
docker run -it -p 8080:8080 tomcat
故意删除上一步镜像生产tomcat容器的文档
以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat02
启动我们的新镜像并和原来的对比
一句话:有点类似我们Redis里面的rdb和aof文件
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
docker inspect 容器ID
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
ro: read only
根目录下新建mydocker文件夹并进入
在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
# volume test
FROM centosVOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash
build后生成镜像
run容器
inspect查看主机对应默认地址
Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied解决办法:在挂载目录后多加一个–privileged=true参数即可
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器
容器间传递共享(–volumes-from)
dockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
3 Docker容器,容器是直接提供服务的。
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
CMD
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
ENTRYPOINT
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合
mkdir -p /zzyyuse/mydockerfile/tomcat9
在上述目录下touch c.txt
将jdk和tomcat安装的压缩包拷贝进上一步目录
在/zzyyuse/mydockerfile/tomcat9目录下新建Dockerfile文件
构建
运行
docker run -d -p 9080:8080 --name myt9
-v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test
-v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zzyytomcat9
验证
docker hub上面查找mysql镜像
从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6
使用mysql5.6镜像创建容器(也叫运行镜像)
docker run -p 12345:3306 --name mysql
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs
-v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
命令说明:
-p 12345:3306:将主机的12345端口映射到docker容器的3306端口。
–name mysql:运行服务名字
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d :将主机/zzyyuse/mysql录下的conf/my.cnf 挂载到容器的 /etc/mysql/conf.d
-v /zzyyuse/mysql/logs:/logs:将主机/zzyyuse/mysql目录下的 logs 目录挂载到容器的 /logs。
-v /zzyyuse/mysql/data:/var/lib/mysql :将主机/zzyyuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
-d mysql:5.6 : 后台程序运行mysql5.6
docker exec -it MySQL运行成功后的容器ID /bin/bash
docker run -p 6379:6379 -v /zzyyuse/myredis/data:/data
-v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf
-d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
镜像的生成方法:前面的DockerFile
阿里云开发者平台 :https://dev.aliyun.com/search.html
创建一个新的镜像:
docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]
创建仓库镜像
将镜像推送到registry
docker login --username= registry.cn-beijing.aliyuncs.com
docker tag [ImageId] registry.cn-beijing.aliyuncs.com/leyton/mycentos:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/leyton/mycentos:[镜像版本号]
命令含义:
第一条登录
第二条提交到阿里云的仓库,并起一个名字与版本号
第三条:push到阿里云的仓库中,名字和版本号与第二条一致