Docker
什么是Docker?
Docker是一个开源的应用容器引擎,基于Go语言开发。
Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
Docker容器完全使用沙箱机制,相互之间不会有任何接口,更重要的容器性能开销极低。
docker官网:https://www.docker.com/
Docker的架构:
Docker包括三个基本概念:
镜像(Image):Docker镜像(Image),就相当于是一个root文件系统。比如官方镜像ubuntu:16.04就包含了完整的一套Ubuntu16.04最小系统的root文件系统
容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类
概念 | 说明 |
---|---|
Docker 镜像(Images) |
Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。 |
Docker 容器(Container) |
容器是独立运行的一个或一组应用,是镜像运行时的实体。 |
Docker 客户端(Client) |
Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。 |
Docker 主机(Host) |
一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
Docker Registry |
Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。 Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。 一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 |
Docker Machine |
Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
Docker的应用场景:
①:Web应用的自动化打包和发布
②:自动化测试和持续继承、发布
③:在服务型环境中部署和调整数据库或其他的后台应用
④:从头编译或者扩展现有的OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
Docker容器使用:
Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序
如:docker run ubuntu:15.10 /bin/echo "Hello world"
docker:Docker的二进制执行文件
run:与docker组合来运行一个容器
ubuntu:15.10 指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像
/bin/echo "Hello world": 在启动的容器里执行的命令
即:Docker以ubuntu15.10镜像创建一个新容器,然后在容器里执行『/bin/echo "Hello world"』,然后输出结果。
运行交互式的容器
通过 docker 的两个参数 -i -t,让 docker 运行的容器可以与我们进行交互
如:docker run -i -t ubuntu:15.10 /bin/bash
-t: 在新容器内指定一个伪终端或终端。
-i: 允许你对容器内的标准输入 (STDIN) 进行交互。
退出终端:
exit命令或ctrl+d
后台运行容器:在大部分场景下,我们希望docker服务是在后台运行的,可以通过 -d 指定容器的运行模式
docker run -itd --name ubuntu-test ubuntu /bin/bash
注:加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec
进入容器:
在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。 docker exec -it 243c32535da7 /bin/bash
停止容器:docker ps -a 查看容器信息, docker stop <容器 ID>
启动已停止运行的容器:docker start 容器id
重启容器:docker restart <容器 ID>
删除容器:docker rm -f <容器 ID>
docker container prune:清理掉所有处于终止状态的容器。
Docker镜像使用:
当运行容器时,使用的镜像如果在本地中不存在,docker就会自动从 docker 镜像仓库中下载,默认是从Docker Hub公共镜像源下载。
获取镜像:docker pull 镜像名:TAG
列出镜像列表:docker images
查找镜像:docker seach 镜像名
删除镜像:docker rmi 镜像名/IMAGE ID
创建镜像:
当我们从docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过一下两种方式对镜像进行更改
1、从已经创建的镜像中更新镜像,并且提交这个镜像
2、使用Dockerfile指令来创建一个新的镜像
更新镜像:
①:更新镜像之前,需要先使用镜像来运行一个容器,如:docker run -t -i ubuntu:15.10 /bin/bash
②:然后在运行的容器内使用 apt-get update 命令进行更新,更新之后,exit指令退出
③:docker commit来提交容器副本
构建镜像:
使用docker build,从零开始来创建一个新的镜像。为此,我们需要创建一个Dockerfile文件,其中包含一组指令来告诉Docker如何构建我们的镜像
①:创建Dockerfile文件
Dockerfile中每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
FROM指令指定使用哪个镜像源
RUN 指令告诉docker 在镜像内执行命令,安装了什么
②:使用Dockerfile构建镜像
docker build -t runoob/centos:6.7 .
-t :指定要创建的目标镜像名
. :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
复制文件或目录到镜像:docker cp 源目录 [docker_image_id]:目标目录
提交修改后的镜像:docker commit -a "你的小米邮箱前缀" -m "本次提交的简要信息" 43c1e670aedc cr.d.xiaomi.net/deploy/镜像名:标签
推送镜像到仓库中:docker push cr.d.xiaomi.net/deploy/镜像名:标签
Docker Dockerfile:
文档:https://docs.docker.com/engine/reference/builder/
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
即使用Dockerfile定制镜像,Docker通过dockerfile来自动构建镜像
FROM:使用的基础镜像源
RUN:用于执行后面跟着的命令行命令
注意:Dockerfile的指令每执行一次都会在docker上新建一层。所以过多无意义的层,会造成镜像膨胀过大。因此 RUN 后面有多个命令的话,以&&符号连接命令,这样执行后,只会创建一层镜像。
RUN命令有两种格式:
shell格式:RUN <命令行命令>
exec格式:RUN ["可执行文件", "参数1", "参数2"]
COPY:复制指令,从上下文路径中复制文件或目录到容器指定路径
上下文路径:是指docker在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令在得知这个路径后,会将路径下的所有内容打包。默认的上下文目录是Dockerfile所在的目录。
注意:上下文路径下不要放无用的文件,因为会一起打包给docker引擎,如果文件过多会造成过程缓慢。
CMD:类似RUN指令,但二者运行的时间点不同:
CMD在docker run时运行
RUN是在docker build
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
ENV:设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
WORKDIR:指定工作目录
用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
问题?
Dockerfile如何使用多个CMD命令?
①:CMD不用中括号框起来,将命令用"&&"符号连接
# 用nohup框起来,不然npm start执行了之后不会执行后面的
CMD nohup sh -c 'npm start && node ./server/server.js'
②:不用CMD,用ENTRYPOINT命令,指定一个执行的shell脚本,然后在entrypoint.sh文件中写上要执行的命令
ENTRYPOINT ["./entrypoint.sh"]
entrypoint.sh文件如下:
// entrypoint.sh
nohup npm start &
nohup node ./server/server.js &
物理机、虚拟化、容器化
物理机:
缺点:部署慢、成本高、资源浪费、难以迁移扩展
虚拟化:
虚拟化在计算机方面通常是指计算元件在虚拟的基础上而不是真实的基础上运行。
虚拟技术是一种将现有的计算机资源(CPU(CPU需支持虚拟化技术)、内存、磁盘空间等)进行组合或分区,使得这些资源表现为一个或多个操作环境,允许一个平台同时运行多个操作系统,并且应用程序可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
虚拟机部署比较迅速,成本低,充分利用了资源,方便迁移和扩展
虚拟机也有一定局限性,每一个虚拟机都是一个完整的操作系统,要分配占用物理机系统资源,当虚拟机多到一定程度时,物理机本身的资源也就被消耗殆尽了
容器化:
虚拟机最终虚拟出了一台完整的计算机系统,其拥有底层的物理硬件、操作系统和应用程序执行的完整环境,都对硬件资源造成了一定的消耗,比较重量化。
Docker可以同时虚拟出多个环境(不是操作系统),每个Docker容器可以部署任意的应用程序,Docker容器内的程序,就好比直接运行在宿主机上,虚拟的每个Docker容器相互独立,互不影响
Docker优点:
①、更有效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用
②、更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间
③、一致的运行环境
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题
④、持续交付和部署
对开发和运维(DevOps (opens new window))人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) (opens new window)系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) (opens new window)系统进行自动部署。
而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像
⑤、更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况
⑥、更轻松的扩展和维护
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像 (opens new window),既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本
Docker仓库管理:
仓库(Repository)是集中存放镜像的地方
Docker Hub,Docker官方维护的公共仓库,https://registry.hub.docker.com/
Docker仓库登录登出:
docker login : 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker logout : 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
登录语法:docker login -u 用户名 -p 密码 [镜像仓库地址]
登出语法:docker logout
如:docker login xxx.cn -u yangyongjie -p xxx
附录:
一、Docker安装Python
1、查找Docker Hub上的Python镜像
docker pull python:TAG
2、使用python镜像
①:在 ~/python/myapp 目录下创建一个 helloworld.py 文件
②:运行容器
docker run -v $PWD/myapp:/usr/src/myapp -w /usr/src/myapp python:3.5 python helloworld.py
-v $PWD/myapp:/usr/src/myapp: 将主机中当前目录下的 myapp 挂载到容器的 /usr/src/myapp。
-w /usr/src/myapp: 指定容器的 /usr/src/myapp 目录为工作目录。
python helloworld.py: 使用容器的 python 命令来执行工作目录中的 helloworld.py 文件
END.