Docker
参考链接:
https://zhuanlan.zhihu.com/p/435605760
dockerfile制作
Docker与虚拟机的区别
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker技术比虚拟机技术更为轻便、快捷。
下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
虚拟机:
虚拟机的Guest OS即为虚拟机安装的操作系统,它是一个完整操作系统内核;虚拟机的Hypervisor层可以简单理解为一个硬件虚拟化平台,它在Host OS是以内核态的驱动存在的。虚拟机实现资源隔离的方法是利用独立的OS,并利用Hypervisor虚拟化CPU、内存、IO设备等实现的。例如,为了虚拟CPU,Hypervisor会为每个虚拟的CPU创建一个数据结构,模拟CPU的全部寄存器的值,在适当的时候跟踪并修改这些值。
Docker:
docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。
由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有优势。
Docker中的三个重要概念
Docker中的三个重要概念分别是:Image(镜像),Container(容器),Repository(仓储)。
Image(镜像)一个特殊的文件系统
你可以把它理解成一个虚拟机的快照(Snapshot),里面包含了你要部署的应用程序以及它所关联的所有库。
操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
Container(容器)镜像运行时的实体
这里的容器就像是一台台运行起来的虚拟机,里面运行了你的应用程序,每个容器是独立运行的他们相互之间不影响。通过一个镜像,我们可以创建许多个不同的Container容器。
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和类的实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
Repository(仓储)集中存放镜像文件的地方
镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务(就像Git仓库一样),Docker Registry就是这样的服务。
一个Docker Registry中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。所以说:镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。
Docker 架构及工作原理
Docker使用客户端-服务器架构。Docker 客户端与 Docker 守护进程通信,后者负责构建、运行和分发Docker容器等繁重的工作。Docker 客户端和守护进程可以运行在同一个系统上,或者您可以将一个 Docker 客户端连接到一个远程 Docker 守护进程。Docker 客户端和守护进程通过 UNIX 套接字或网络接口使用 REST API 进行通信。
Dockerfile(自动化脚本)
主要是用来创建我们之间讲到的镜像,这个过程就好比我们在虚拟机中安装操作系统和软件一样,只不过是通过Dockerfile这个自动化脚本完成的。
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
简单来说,Dockerfile就是把我们安装环境的每个步骤和指令,放到一个文件,最后一键执行,最后做成一个你想要的环境。
Docker构建三步曲:
- 编写dockerfile文件
- docker build 构建image镜像文件
- docker run 运行容器
Dockerfile相关指令
Dockerfile 是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据 Dockerfile 的内容构建镜像,
在介绍如何构建之前先介绍下 Dockerfile 的基本语法结构。
Dockerfile 有以下指令选项:
- FROM 基础镜像,当前新镜像是基于哪个镜像的
- MAINTAINER 镜像维护者的姓名和邮箱地址
- RUN 容器构建时需要运行的命令
- CMD 指定一个容器启动时要运行的命令。
dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换。
- EXPOSE 当前容器对外暴露的端口号
- ENV 用来在构建镜像过程中设置环境变量
- ADD 将宿主机目录下的文件拷贝到镜像里面并且ADD命令会自动处理URL和解压tar压缩包
- COPY COPY:类似ADD,拷贝文件和目录到镜像中,但是它只是拷贝,不会自动处理URL和解压tar压缩包。
- ENTRYPOINT 指定一个容器启动时要运行的命令。
- ENTRYPOIT的目的和CMD一样,都是在指定容器启动程序及参数。
- VOLUME 容器数据卷,用于数据保存和持久化工作
- USER 指定运行容器时的用户名或UID,后续的 RUN 也会使用指定用户
- WORKDIR 指定在容器创建后,终端默认登录进来工作目录,一个落脚点
- ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后,父镜像的onbuild被触发。
Dockerfile编写
在当前目录新建一个文件夹docker-run, cd进入到文件夹,touch新建一个Dockerfile,然后vi打开文件,开始编辑
[root@yoyo ~]# mkdir docker-run
[root@yoyo ~]# cd docker-run/
[root@yoyo docker-run]# touch Dockerfile
[root@yoyo docker-run]# vi Dockerfile
编辑内容如下:
# 基于python3.6.8镜像
FROM python:3.6.8
MAINTAINER yoyo <283340479@qq.com>
# 更新pip
RUN pip install --upgrade pip
# 工作目录
WORKDIR /code
ADD . /code
# pip安装依赖包
RUN pip install -r requirements.txt
# 传递参数
ENTRYPOINT ["pytest"]
# 默认显示help帮助信息
CMD ["--help"]
requirements.txt
requirements.txt是python的相关依赖包, 可以通过freeze命令生成
pip3 freeze >requirements.txt
[root@yoyo docker-run]# cat requirements.txt
APScheduler==3.5.3
asn1crypto==0.24.0
atomicwrites==1.3.0
attrs==18.2.0
backports.csv==1.0.7
bcrypt==3.1.7
beautifulsoup4==4.7.1
cached-property==1.5.1
certifi==2018.11.29
cffi==1.12.3
chardet==3.0.4
cryptography==2.7
DBUtils==1.3
defusedxml==0.5.0
diff-match-patch==20181111
Django==2.1.4
django-bootstrap3==11.0.0
django-crispy-forms==1.7.2
django-formtools==2.1
django-import-export==1.2.0
django-ranged-response==0.2.0
django-reversion==3.0.3
django-simple-captcha==0.5.10
django-stdimage==4.0.1
docker==3.7.3
docker-compose==1.24.1
docker-pycreds==0.4.0
dockerpty==0.4.1
docopt==0.6.2
et-xmlfile==1.0.1
future==0.17.1
httplib2==0.12.1
idna==2.7
jdcal==1.4
jsonschema==2.6.0
more-itertools==6.0.0
mysqlclient==1.4.2.post1
odfpy==1.4.0
openpyxl==2.6.1
paramiko==2.6.0
Pillow==5.4.1
pluggy==0.6.0
progressbar2==3.39.3
py==1.7.0
pycparser==2.19
pymssql==2.1.4
PyMySQL==0.9.3
PyNaCl==1.3.0
pytest==3.6.3
python-utils==2.3.0
pytz==2018.7
PyYAML==3.13
requests==2.20.1
six==1.12.0
soupsieve==1.7.3
tablib==0.13.0
texttable==0.9.1
tzlocal==1.5.1
urllib3==1.24.1
websocket-client==0.56.0
xlrd==1.2.0
xlwt==1.3.0
build构建镜像文件
docker build 命令用于使用 Dockerfile 创建镜像。OPTIONS说明:
- -f :指定要使用的Dockerfile路径;
- —pull :尝试去更新镜像的新版本;
- —quiet, -q :安静模式,成功后只输出镜像 ID;
- —tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
-t参数设置镜像名称yoyo_pytes和tag标签名称v1,注意最后面有个点.
docker build -t yoyo_pytest:v1 .
[root@yoyo docker-run]# docker build -t yoyo_pytest:v1 .
Sending build context to Docker daemon 11.78kB
Step 1/8 : FROM python:3.6
---> cfcdf565ff94
Step 2/8 : MAINTAINER yoyo <283340479@qq.com>
---> Using cache
---> f523b919fcf9
Step 3/8 : RUN pip install --upgrade pip
---> Using cache
---> 3399b50dab4e
Step 4/8 : WORKDIR /code
---> Using cache
---> 7223a20e17fd
Step 5/8 : ADD . /code
---> 650b554ccd6c
Step 6/8 : RUN pip install -r requirements.txt
---> Running in 0e49d444f7d8
运行过程中可以看到按步骤运行,如:Step 1/8
运行完成后,可以通过docker images查看生成的镜像
[root@yoyo docker-run]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
yoyo_pytest v1 6b4267ce7ac4 21 seconds ago 1.02GB
[root@yoyo docker-run]#
run运行容器
在当前目录新建一个test_h.py文件,写入pytest测试脚本
import pytest
def test_one():
print("正在执行----test_one")
x = "this"
assert 'h' in x
def test_two():
print("正在执行----test_two")
x = "hello"
assert x
def test_three():
print("正在执行----test_three")
a = "hello"
b = "hello world"
assert a in b
if __name__ == "__main__":
pytest.main(["-s", "test_h.py"])
使用docker run运行容器
- -it -t让docker分配一个伪终端并绑定到容器的标准输入上, -i则让容器的标准输入保持打开.
- —rm 容器退出时,自动清除容器。
—rm选项不能与-d同时使用 - -v 将容器的工作目录/code挂载到宿主机的$PWD,也就是当前目录
- yoyo_pytest:v1 容器名称和tag名称
- test_h.py 后面跟着需要执行的脚本名称
[root@yoyo docker-run]# docker run -it --rm -v "$PWD":/code yoyo_pytest:v1 test_h.py -s
================================================================== test session starts ==================================================================
platform linux -- Python 3.6.9, pytest-3.6.3, py-1.7.0, pluggy-0.6.0
rootdir: /code, inifile:
collected 3 items
test_h.py 正在执行----test_one
.正在执行----test_two
.正在执行----test_three
.
=============================================================== 3 passed in 0.01 seconds ================================================================
[root@yoyo docker-run]#