1. 容器是什么?

 容器是一种轻量级操作系统层面的虚拟化,它为应用软件及其依赖组件提供了一个资源独立的运行环境。应用软件所依赖的组件会被打包成一个可重用的镜像,镜像运行环境并不会与主操作系统共享内存、CPU和硬盘空间,由此也保证了容器内部的进程与容器外部进程的独立关系。
 而虚拟机的每个实例自带操作系统,因而是一种硬件级的虚拟化隔离。
Docker是当前流行的开源容器虚拟化平台;

2. docker原理与架构

Docker实现原理2个重要概念:namespace,cgroup,
 其中,namespace(命名空间)用来做容器与宿主机的隔离,cgroup用来做内存、存储等资源的限制;
Docker三大组件:镜像、仓库、容器
 Docker 镜像:镜像 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。
 Docker 仓库:仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker 仓库分为公有仓库和私有仓库,公有仓库就是Docker官方的仓库:Docker Hub,私有仓库可以自己进行搭建;
  Docker 容器:一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。

3. 安装

本次实验使用系统为红帽企业7.3,安装Docker18.06.1社区版,以下的所安装的docker级所需要的依赖性的RPM包:
在这里插入图片描述开启docker:
在这里插入图片描述在这里插入图片描述注意:docker开启后在宿主机会出现一块虚拟网卡docker,docker运行起来后,所有运行的容器都使用内网地址,默认情况下docker与宿主机的网络使用桥接网络:
在这里插入图片描述

4. 使用:

  1. 第一个docker容器:
    准备镜像(此镜像是已经压制好的镜像,后面会学习如何压制自己的镜像):在这里插入图片描述导入镜像:
    在这里插入图片描述运行容器:
    在这里插入图片描述查看正在运行的容器:
    在这里插入图片描述由于我们在启动容器时进行了端口映射,所以此时宿主机上的8080端口已经开启:
    在这里插入图片描述访问宿主机的8080端口,则可以看到2048小游戏的界面(可以在此界面上正常玩游戏):
    在这里插入图片描述2. Dcoker常用命令:
docker
	run			##创建并启动容器
		-it		##交互式终端
		--rm	##退出容器时自动删除容器
		--name	##指定容器名称
		-d		##容器后台运行
	
	  ps		##查看当前的容器
		-a		##所有容器
	
	  rm		##删除容器
		-f		##强制删除
	
	  rmi		##删除镜像
	  	-f		##强制删除
	
	  attach	##进入容器	  
	  commit	##提交
	  			
	  contanier		##容器的命令
		cp			##将指定的文件cp到容器内指定的位置
		prune		##删除所有停止的容器	
		exec	CMD	##容器内执行CMD命令
		export		##将一个容器打包成tar包
			
	  diff			##查看容器的变更
		
	  logs			##查看容器的日志
	
	  insepc		##查看容器的详细状态
	
	  history		##看到此容器的历史

附一张高大上的docker命令图:
在这里插入图片描述
3.Docker使用之镜像:
从上面的实验可以看出,docker的镜像是docker的基石,而若要满足个性化的需求,就需要我们自己来压制所需要的镜像,docker的镜像压制有自己的一套规则,Dockerfile文件中存储定制镜像的一系列命令,编写Dockerfile的规则如下:

# FROM:设置要制作的镜像基于哪个镜像
# 第一条指令必须为 FROM 指令 
# usage:FROM <image> 
#  FROM <image>:<tag>
FROM rhel7 

# MAINTAINER 维护者信息
# usage: MAINTAINER <name>
MAINTAINER wx

# ADD 将源文件复制到目的容器指定目录下,如果源是一个URL,那该URL的内容将被下载并复制到容器中
# ADD 把包添加到容器指定目录,如果是tar包会自动解压
# ADD 后跟的源码包必须与Dockerfile置于同一目录下
# usage: ADD <src or URL> <dest>
ADD nginx-1.15.7.tar.gz /usr/local/

# COPY 将本地的源系统复制到目标容器指定目录下
# usage:COPY <src> <dest>
# COPY yum.repo /etc/yum.repos.d/yum.repo

# RUN 在容器中运行命令
# usage: RUN <command> 在shell中运行命令,即"/bin/bash -c"
# RUN ["executable","param1", "param2"] 指定exec来执行命令
# 指定使用其它终端可以通过第二种方式实现,例如 RUN [“/bin/bash”, “-c”,”echo hello”]
#RUN yum clean all && yum repolist && yum install gcc pcre*
make openssl-devel zlib-devel -y && yum clean all 

# WORKDIR 指定容器的一个目录,容器启动时执行的命令会在该目录下执行,相当于设置了容器的工作目录
# 此命令类似cd
# 为后续的 RUN,CMD,ENTRYPOINT 指令配置工作目录.可以使用多个WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径
# WORKDIR 可以用来做目录的切换 
# usage:WORKDIR /path/to/workdir
# WORKDIR /usr/local/nginx-1.15.7

# RUN 在容器中运行命令并进行编译安装
ADD yum.repo /etc/yum.repos.d/rhel7.repo
RUN rpmdb --rebuilddb &&  yum
clean all && yum swap fakesystemd systemd -y \
 && yum install gcc pcre* make
openssl-devel zlib-devel -y && yum clean all \
 && useradd -s /sbin/nologin -M
nginx \
 && cd /usr/local/nginx-1.15.7/  \
 && ./configure --prefix=/usr/local/nginx && make && make install \
 && ln -s
/usr/local/nginx/sbin/nginx /usr/local/sbin \
 && chmod +x
/usr/local/sbin/nginx

# ENV指令用于设置环境变量,在Dockerfile中这些设置的环境变量也会影响到RUN指令,当运行生成的镜像时这些环境变量依然有效
# ENV 将nginx启动命令添加到系统环境变量里
# usage:ENV <key> <value>
#  ENV <key>=<value>
# ENV PATH /usr/local/nginx/sbin/:$PATH

# EXPOSE指令用来告诉Docker这个容器在运行时会监听哪些端口
# EXPOSE 暴露80端口
# usage:EXPOSE <port>
EXPOSE 80

# CMD 指定启动容器时执行的命令
# 当有多个CMD命令时,只有最后一个CMD命令会被执行
# usage:CMD ["executable","param1","param2"]
# CMD command param1 param2 在 /bin/bash 中执行
# CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数
# 启动容器时开启nginx
# WORKDIR /usr/local/nginx/sbin
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]

实例:基础镜像:rhel7.3;目标:压制http镜像:
1.新建docker目录:
 ##不要在/ 底下编译,否则会将/ 下的所有文件都编译一遍,所以应该新建一个空目录来编译
在这里插入图片描述2.编写Dockerfile如下:
在这里插入图片描述3.导入基础镜像rhel7(若本地不存在此镜像,默认会从官方的镜像仓库拉取):
在这里插入图片描述4.将所需的copy文件与Dockerfile放置在同一目录下:
在这里插入图片描述5.压制镜像:
在这里插入图片描述查看:
在这里插入图片描述
6.启动容器:
在这里插入图片描述注意:ps选项只会显示出当前正在运行的容器,不会显示出停止的容器,若想显示所有的容器,需要添加-a/-all选项:
在这里插入图片描述8.测试:
启动容器apache:
在这里插入图片描述查看容器详细信息:
在这里插入图片描述
可以看到容器的地址:
在这里插入图片描述写一个自己的index.html,内容如下:
在这里插入图片描述将此文件放入容器中apache默认发布目录下,访问容器,返回我们的index文件内容,这说明容器正常运行,镜像压制无误:
在这里插入图片描述3.ENV & CMD & ENTYRYPOINT:

1.ENV:定义全局变量
  “测试:”
  #1.Dockerfile如下:
  	FROM busybox
	ENV name world
	CMD echo "hello $name"
    输出:
	[root@server1 test1]# docker run --rm test:v1
	hello world

  #2.Dockerfile如下:
	FROM busybox
	ENV name world
	CMD ["/bin/echo","hello $name"]
     输出:
	[root@server1 test1]# docker run --rm test:v2
	hello $name	##若要解析,需指定-e参数
	
  #3.Dockerfile如下:
	FROM busybox
	ENV name world
	CMD ["/bin/sh","-c","echo hello,$name"]	
		##/bin/sh 是 /bin/bash的软链接,使用man bash可以查看bash命令的具体使用方法;
    输出:
	[root@server1 test1]# docker run --rm test:v3
	hello,world

  #4.Dockerfile如下:
	FROM busybox
	ENTRYPOINT ["/bin/echo","hello"]
	CMD ["world"] 
    输出:
	[root@server1 test1]# docker run --rm test:v4
	hello world
 
	[root@server1 test1]# docker run --rm test:v4 westos
    hello westos

结论:
 ##两者的相同之处:都是在运行容器时被执行
 ##不同之处:CMD可以被覆盖,但是ENTRYPOINT不会被覆盖
 ##同时:如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数

4.镜像的缩减:
  #1.减少RUN命令:将RUN命令尽量写在一起,使用 \ 换行或者 && 进行级联执行
  #2.可以将需要编译的软件在外面编译好,将安装包cp进容器即可
  #3.镜像多阶段构建:
首先看不经过多阶段构建是镜像的大小:
Dockerfile如下:
在这里插入图片描述将nginx源码包和yum源配置与Dockerfile放在同一目录下构建镜像:
在这里插入图片描述在这里插入图片描述可以正常运行:
在这里插入图片描述可以看到源码编译安装后镜像体积相比基础镜像大了90M,这会使得镜像臃肿从而失去了docker轻量级的优势,但是很多软件是需要我们进行源码编译的,此时我们就可以先编译好在直接拿来用:
Dcokerfile如下:
在这里插入图片描述构建镜像:
在这里插入图片描述此时镜像大小:
在这里插入图片描述此时镜像只比基础镜像多了1M,但它的功能仍是完美无缺的:
在这里插入图片描述注意:在镜像构建过程中,实际上是分层构建的,因此首先应减少Dockerfile的层数,同时由于构建过程中会产生cache,所以对于多次构建的镜像(以前构建失败的镜像在使用images命令列出时也会出现),只会在第一次构建某一层时真正进行操作(若没有删除构建失败的镜像时),同时在仓库拉取或上传镜像时,若检测到有哪一层仓库中已经存在了,就不再进行拉取或者上传,这使得镜像实现了复用的功能。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐