Docker 相关概念
镜像
我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:14.04 就包含了完整的一套 Ubuntu 14.04 最小系统的 root 文件系统。
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变.
分层存储
因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。 每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。
Docker安装
windows安装
-
对于Windows 10以下的用户 推荐使用 Docker Toolbox
-
Windows系统的安装文件目录:http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/
-
对于Windows 10以上的用户 推荐使用 Docker for Windows
-
Windows系统的安装文件目录:http://mirrors.aliyun.com/docker-toolbox/windows/docker-for-windows/
-
MAC安装
-
对于10.10.3以下的用户 推荐使用 Docker Toolbox
-
Toolbox的介绍和帮助:mirrors.aliyun.com/help/docker-toolbox
-
Mac系统的安装文件目录:http://mirrors.aliyun.com/docker-toolbox/mac/docker-toolbox/
-
-
对于10.10.3以上的用户 推荐使用 Docker for Mac
镜像加速器
-
配置加速器地址
- windows
请在客户端菜单Settings-Daemon的Registry-mirrors选项框里填写上加速地址https://gzv8r4j3.mirror.aliyuncs.com -
mac
preferences -> daemon -> Advanced
- windows
Dockerfile使用
Dockerfile示例
Dockerfile 关键字说明
FROM
指定基础镜像
每一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
RUN
执行命令
shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样
ENV
指定一个环境变量,会被后续相关指令使用,并在容器运行时保持。
下列指令可以支持环境变量展开: ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD
COPY
将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
ADD
和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能, 比如:可以自动解压,可以从一个URL地址下载文件并将文件设置权限为600.
需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
WORKDIR
指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
在RUN命令中使用cd来切换目录,这种做法是无效的,在dockerfile中,切换目录的正确做法是使用WORKDIR命令来切换目录
EXPOSE
声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
CMD
用于指定默认的容器主进程的启动命令的。
在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号。
ENTRYPOINT
容器启动时执行的命令,和CMD类似。CMD指令指定的容器启动时命令可以被docke r run指定的命令覆盖,而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
docker运行注意事项
提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念。
一些初学者将 CMD 写为:
然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "service nginx start"],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。
正确的做法应该是:
Docker使用
- 基础镜像
java:openjdk-8-jre-alpine
node:7.9.0-alpine
maven:3.5.0-jdk-8-onbuild-alpine - 如何创建镜像
- 将Dockerfile文件放在程序根目录下
-
运行 docker build 命令构建镜像
-
查看本地镜像
-
删除镜像
-
如何基于镜像运行容器
示范