一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。 作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题, 特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验 . Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。
环境配置如此麻烦,换一台机器,就要重来一次,费力费时。 很多人想到,能不能从根本上解决问题,软件可以带环境安装? 也就是说,安装的时候,把原始环境一模一样地复制过来。 开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。
开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。 不过,即便如此,仍然常常发生部署失败的状况。 Docker镜像的设计,使得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 Containers,缩写为 LXC)。 Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。 有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。 容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。 系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
二者区别
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主机( 即:所在主机,下面统称宿主机 ) 的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。官方网址 : https://www.docker.com Docker社区官方:https://hub.docker.com/
Docker支持以下的CentOS版本:CentOS 7 (64-bit) ,CentOS 6.5 (64-bit) 或更高的版本
目前,CentOS 仅发行版本中的内核支持 Docker。 Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。 Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。
# 查看内核版本 uname -r 12Docker安装教程(CentOS 7)本人安装成功
Docker安装教程(CentOS 6)
# 启动docker容器 ,每次关闭虚拟机/运服务器时需要启动( 重要!!! ) sudo service docker start
# 查看Docker容器状态 sudo service docker status (should see active (running))
# 运行hello-world镜像/测试Docker是否可以使用 sudo docker run hello-world
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。
(1) docker有着比虚拟机更少的抽象层。 由亍docker不需要Hypervisor实现硬件资源虚拟化, 运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。 因此在CPU、内存利用率上docker将会在效率上有明显优势。
(2) docker利用的是宿主机的内核,而不需要Guest OS。 因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。 因而避免引寻、加载操作系统内核返个比较费时费资源的过程, 当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。 而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。 通过下图着重了解二者的比较( 图很重要!!!)
docker info
docker --help
-a :列出所有镜像 -q:只列出镜像id -digests :显示镜像的摘要信息 –no-trunc :显示相信信息
docker search
docker pull 镜像的名字:[TAG](不写默认为 lasted)
docker rmi -f 镜像名/镜像id docker rmi -f $(docker images -qa )
各个选项说明: REPOSITORY:表示镜像的仓库源 TAG:镜像的标签 IMAGE ID:镜像ID CREATED:镜像创建时间 SIZE:镜像大小 同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。 如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
图1 图2
图3
docker run -it centos /bin/bash
docker ps [OPTIONS]
exit 容器停止后退出 ctrl+p+q 容器不停止退出
docker start 容器ID/容器名
docker restart
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
问题:然后docker ps -a 进行查看, 会发现容器已经退出 很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程. 容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start 但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用, 这样的容器后台启动后,会立即自杀因为他觉得他没事可做了. 所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行
eg :(图1) docker run -d centos /bin/sh -c “while true;do echo hello testLogs;sleep 2;done” docker logs -tf --tail 10 02c81778b0e0
-t 是加入时间戳 -f 跟随最新的日志打印 –tail 数字 显示最后多少条
docker top 容器ID
docker inspect 容器ID
docker exec -it 容器ID bashShell
docker attach 容器ID bashShell(不写的话默认 /bin/bash下)
attach 直接进入容器启动命令终端, 不会启动新的线程 exec 是在容器中打开新的终端, 并且可以启动新的线程
图1
图2 图3 图4 图5
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下。Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承. 基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统, 联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
总结: 镜像就像洋葱圈 ,就像莲花卷 ,一层套一层 ,对外只显示一个文件系统. 而且, 这种分层镜像还可以复用
Dcoker镜像都是只读的 , 当启动容器时, 一个新的可写层被加载到镜像的顶部 这一层被称为"容器层", "容器层"执行的都称为"镜像层"
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等等。
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了, 因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。 由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
eg: 同时docker运行tomcat案例
docker run -it -p 8888:8080 tomcat # 端口映射将8888作为docker的入口,映射到tomcat镜像的8080(图1,图2) docker run -it -P tomcat #自动端口映射(通过 docker ps查看端口, 图3) #后台启动(不会占用当前页面) docker run -d -p 8888:8080 tomcat
docker ps
docker exec -it 容器ID /bin/bash /usr/local/tomcat# rm -rf webapps/docs/
docker ps
docker commit -m=“del tomcat docs” -a=“timepaus” 容器ID tomcat:v1.2
docker images
可以看到我们自己提交的新镜像也没有文档() 但是我们重新下载的tomcat是有的
图1 图2 图3 图4
图5
类似Redis中的rdb文件和aof文件 用于容器的持久化和荣期间的继承与共享数据
docker run -it -v /宿主机绝路路径目录:/容器内目录:ro 镜像名
DockerFile的简单理解
# 1. 宿主机根目录下创建mydocker文件夹并进入FROM centos VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] CMD echo “finished,--------success1” CMD /bin/bash
说明: 出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
使用docker build命令创建一个镜像, 并挂载指定宿主机指定文件 docker build -f /mydocker/DockerFile -t 定义的新镜像名称
查看镜像 docker images
5.运行新镜像 docker run -it 定义的新镜像ID /bin/bash
6.通过镜像运行后生成的容器ID查看 (图2), 对应的主机映射的数据卷地址 docker ps docker inspect 容器ID
7.测试添加卷和主机是否互通有无 在容器中创建文件, 看看主机中是否创建对应的文件
注意: Docker挂载主机目录(第3步)Docker访问出现cannot open directory .: Permission denied 解决办法:在挂载目录后多加一个–privileged=true参数即可
图1
图2, 查看运行的容器id相关信息 docker inspect 容器ID 对比与总结
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享, 挂载数据卷的容器,称之为数据卷容器
实现步骤
# 1. 以上一步所建镜像为模板 ,首先启动一个父容器dc01 ,在创建容器的数据卷文夹中创建一个文件(图1) docker run -it --name dc01 zzyy/centos touch dc01_add.txtdocker run -it --name dc02 --volumes-from dc01 zzyy/centos touch dc02_add.txt docker run -it --name dc03 --volumes-from dc01 zzyy/centos touch dc01=3_add.txt
结论 容器之间配置信息的传递, 数据卷的生命周期一直持续到没有容器使用它为止
图1 图2 图3 图4
图5 图6
Dockerfile是用来构建Docker镜像文件 ,是有一系列命令和参数构成的脚本
1.编写Dockerfile文件 2.docker build 3.docker run
以centos的文件为例
FROM scratch ADD centos-8-container.tar.xz /LABEL org.label-schema.schema-version=“1.0” org.label-schema.name=“CentOS Base Image” org.label-schema.vendor=“CentOS” org.label-schema.license=“GPLv2” org.label-schema.build-date=“20190927”
CMD ["/bin/bash"]
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料Docker镜像是软件的交付品Docker容器则可以认为是软件的运行态。Dockerfile面向开发,Docker镜像成为交付标准, Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等; 2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务; 3 Docker容器,容器是直接提供服务的
查看tomcat的DockerFile文件 ,更好理解保留字
我们安装的centos精简版是没有vim和ifconfig命令的支持的 我们可以通过编写Dockerfile令其支持这些功能
# 1.搜索centos镜像并下载 docker search centos docker pull centosFROM centos MAINTAINER timepause<qq_43371556@csdn.net>
ENV MYPATH /usr/local WORKDIR $MYPATH
RUN yum -y install vim RUN yum -y install net-tools
EXPOSE 80
docker build -f /mydoker/dockerfile_centos -t mycentos:1.3 .
docker ps
docker run -it mycentos:1.3
图1
图2
touch c.txt
#. 4.创建并编辑Dockerfile(需要提前下载centos) vim Dockerfile ---------------------Dockerfile------------------------------- FROM centos MAINTAINER chy<chy@qq.com> #把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下 COPY c.txt /usr/local/cincontainer.txt #把java与tomcat添加到容器中 ADD jdk-8u11-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.27.tar.gz /usr/local/ #安装vim编辑器 RUN yum -y install vim #设置工作访问时候的WORKDIR路径,登录落脚点 ENV MYPATH /usr/local WORKDIR $MYPATH #配置java与tomcat环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH J A V A H O M E / l i b / d t . j a r : JAVA_HOME/lib/dt.jar: JAVAHOME/lib/dt.jar:JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.27 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.27 ENV PATH P A T H : PATH: PATH:JAVA_HOME/bin: C A T A L I N A H O M E / l i b : CATALINA_HOME/lib: CATALINAHOME/lib:CATALINA_HOME/bin #容器运行时监听的端口 EXPOSE 8080 #启动时运行tomcat
CMD /usr/local/apache-tomcat-9.0.27/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.27/bin/logs/catalina.out ---------------------Dockerfile-------------------------------
docker build -t mytomcat9 .
docker images
docker run -d -p 8080:8080 --name myt9 -v /myuse/mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.27/webapps/test -v /myuse/mydocker/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.27/logs --privileged=true mytomcat9
docker -it 容器ID /bin/bash #进入容器根目录 ,可以访问相关页面
vim a.jsp mkidr WEB-INF vim /WEB-INF/web.xml ------------------------------------------a.jsp--------------------------- <%@ page language=“java” contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%> <!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”> <html> <head> <meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”> <title>Insert title here</title> </head> <body>
-----------welcome------------ <="i am in docker tomcat self "%> <br> <br> <% System.out.println("=============docker tomcat self");%></body> </html> ------------------------------------------a.jsp---------------------------
------------------------------------------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> ------------------------------------------web.xml-----------------------------------
docker ps (查看当前容器ID) docker ps -a (查看所有运行过的容器ID)
docker restart 容器ID
图1 图2
图3 图4
图5
docker run -p 3306:3306 --name mysql -v /datebase/mysql/conf:/etc/mysql/conf.d -v /datebase/mysql/logs:/logs -v /datebase/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.6
docker ps docker exec -it MySQL运行成功后的容器ID /bin/bash
docker exec myql服务容器ID sh -c ’ exec mysqldump --all-databases -uroot -p"root" ’ > /datebase/all-databases.sql
docker run -p 2333:6379 -v /myuse/myredis/data:/data -v /myuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
本地数据卷坐在目录 : /myuse/myredis/conf 文件地址(太大了 ,这里放不下) : https://download.csdn.net/download/qq_43371556/11889084
docker exec -it 运行着Rediis服务的容器ID redis-cli
docker run -d --name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 -v pwd/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=/ -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin df80af9ca0c9
-d 后台运行容器; –name 指定容器名; -p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号); -v 映射目录或文件; –hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名); -e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)
http://ip:15672 账号 :admin 密码: admin
docker commit
OPTIONS说明: -a :提交的镜像作者; -m :提交时的说明文字;
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号] sudo docker push registry.cn-hangzhou.aliyuncs.com/timepause/mydocker:[镜像版本号]
docker pull 复制的镜像地址
图1 图2 图3
图4 图5 图6
点击本博客相关学习视频地址
</div> <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e9f16cbbc2.css" rel="stylesheet"> </div>