目录

一.获取镜像

Docker运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。

从Docker镜像仓库获取镜像的命令是docker pull,其命令格式为:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

如:

$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
297061f60c36: Pull complete
e9ccef17b516: Pull complete
dbc33716854d: Pull complete
8fe36b178d25: Pull complete
686596545a94: Pull complete
Digest: sha256:1dfb94f13f5c181756b2ed7f174825029aca902c78d0490590b1aaa203abc052
Status: Downloaded newer image for ubuntu:16.04

上面的命令中没有给出Docker镜像仓库地址,因此将会从Docker Hub获取镜像(如果配置镜像加速器,则从镜像加速器上拉取镜像)。而镜像名称是ubuntu:16.04,因此将会获取官方镜像library/ubuntu仓库中标签为16.04的镜像。

从下载过程中可以看到我们之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的ID前12位,并且下载结束后,给出该镜像完整的sha256的摘要,以确保下载一致性。

二.使用镜像启动容器实例

使用命令:docker run从镜像启动容器实例。

$ docker run -it --rm ubuntu:16.04 bash

docker run就是运行容器的命令,简要的说明一下上面用到的参数。

-it:这是2个参数,一个是-i:交互式操作,一个-t:终端。

--rm:这个参数说明容器退出之后随之将其删除。默认情况,不使用--rm参数启动的容器在退出之后不会立即删除,除非使用命令明确删除:docker rm

ubuntu:16.04:指定使用ubuntu:16.04这个镜像为基础启动容器

bash:放在镜像名之后的是命令,即:启动容器之后在容器中执行的命令

使用exit命令退出容器。

三.列出镜像

使用docker image ls命令列出当前已经下载到本地的镜像。

$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 0b1edfbffd27 4 days ago 113MB
hello-world latest e38bc07ac18e 2 weeks ago 1.85kB

输出列表中包含了仓库名,标签,镜像ID,创建时间和所占用的空间。

镜像ID则是镜像的唯一标识,一个镜像可以对应多个标签(不同标签下的同一个镜像的ID值相同)。

四.删除本地镜像

$ docker image rm <镜像id>

五.定制镜像

镜像的定制实际上就是定制每一层所添加的配置和文件,定制镜像有2种方式:commit,Dockerfile。

通过commit命令定制镜像

使用镜像启动容器实例之后,在容器内部做的所有修改,都可以使用commit命令将容器存储层保存为镜像。如:

$ docker commit --author "zhangsan@xxx.com" --message "modify default index page content" webserver nginx:v2

--author指定修改的作者,而--message则是记录本次修改的内容,webserver为容器名称,nginx:v2为需要保存为的镜像仓库名和标签。

慎用docker commit命令保存镜像!制作镜像应该使用Dockerfile实现。使用docker commit命令保存镜像存在一些缺陷:

首先,在对容器进行配置时,会涉及多个文件的修改或添加,但其实有些文件是不需要保存为镜像的,如果不进行小心清理,会导致最终保存的镜像文件过于臃肿。

其次,使用命令方式意味着所有对镜像的操作都是黑箱的,不利于重现镜像制作的步骤,以及后期的维护。

通过Dockerfile定制镜像

通过Dockerfile定制镜像就是把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。

Dockerfile是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

使用了docker build命令进行镜像构建,其格式为:

docker build [选项] <上下文路径/URL/->

例如: $ docker build -t nginx:v3 .

docker build的工作原理

首先我们要理解docker build的工作原理。Docker在运行时分为Docker引擎(也就是服务端守护进程)和客户端工具。Docker的引擎提供了一组REST API,被称为Docker Remote API,而如docker命令这样的客户端工具,则是通过这组API与Docker引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种Docker功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成的。也因为这种C/S设计,让我们操作远程服务器的Docker引擎变得轻而易举。

当我们进行镜像构建的时候,并非所有定制都会通过RUN指令完成,经常会需要将一些本地文件复制进镜像,比如通过COPY指令,ADD指令等。而docker build命令构建镜像,其实并非在本地构建,而是在服务端,也就是Docker引擎中构建的。那么在这种C/S架构中,如何才能让服务端获得本地文件呢?这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build命令得知这个路径后,会将路径下的所有内容打包,然后上传给Docker引擎。这样Docker引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。如果在Dockerfile中这么写:“COPY ./package.json /app/”,这并不是要复制执行docker build命令所在的目录下的package.json ,也不是复制Dockerfile所在目录下的 package.json ,而是复制上下文(context)目录下的package.json。因此,COPY这类指令中的源文件的路径都是相对路径。这也是初学者经常会问的为什么“COPY ../package.json /app”或者“COPY /opt/xxxx /app”无法工作的原因,因为这些路径已经超出了上下文的范围,Docker引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。

现在就可以理解刚才的命令docker build -t nginx:v3 .中的这个.实际上是在指定上下文的目录,docker build命令会将该目录下的内容打包交给Docker引擎以帮助构建镜像。

如果观察docker build输出,我们其实已经看到了这个发送上下文的过程:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
...

理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现COPY /opt/xxxx /app不工作后,于是干脆将Dockerfile放到了硬盘根目录去构建,结果发现docker build执行后,在发送一个几十GB的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让docker build打包整个硬盘,这显然是使用错误。

一般来说,应该将Dockerfile置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给Docker引擎,那么可以用.gitignore一样的语法写一个.dockerignore ,该文件是用于剔除不需要作为上下文传递给Docker引擎的。那么为什么会有人误以为“.”是指定Dockerfile所在目录呢?这是因为在默认情况下,如果不额外指定Dockerfile的话,会将上下文目录下的名为“Dockerfile”的文件作为构建镜像需要的Dockerfile。这只是默认行为,实际上Dockerfile的文件名并不要求必须为Dockerfile,而且并不要求必须位于上下文目录中,比如可以用“-f ../Dockerfile.php”参数指定某个文件作为Dockerfile 。

当然,一般大家习惯性的会使用默认的文件名Dockerfile,以及会将其置于镜像构建上下文目录中。

docker build的用法

docker build的基本语法为:docker build [选项] <上下文路径/URL/->,从语法中可以很明显地看出该命令支持多种构建方式.

1.从本地文件系统构建

$ docker build -t nginx:v3 .

上述构建操作包含2个参数:

"-t"指定镜像标签名称

"."指定构建上下文路径

2.从Git仓库构建

$ docker build https://github.com/nuccch/docker_test#:8.14

这行命令指定了构建所需的Git仓库,并且指定默认的master分支,构建目录为/8.14/,然后Docker就会自己去 git clone这个项目、切换到指定分支、并进入到指定目录后开始构建。

说明: 从Git仓库中构建Docker镜像是在实际项目中使用得比较多的方式,开发者只需要将代码提交到指定Git仓库的指定分支,测试只需要从该仓库的分支上构建Docker镜像即可.

3.用给定的tar压缩包构建

$ docker build http://server/context.tar.gz

如果所给出的URL不是个Git仓库,而是个tar压缩包,那么Docker引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。

4.从标准输入中读取Dockerfile进行构建

$ docker build - < Dockerfile

或者

$ cat Dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为Dockerfile ,并开始构建。

注意: 这种形式由于直接从标准输入中读取Dockerfile的内容,它没有上下文,因此不可以存在像其他方法那样可以将本地文件COPY进镜像之类的事情。

5.从标准输入中读取上下文压缩包进行构建

$ docker build - < context.tar.gz

如果发现标准输入的文件格式是gzip,bzip2以及xz的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。

【参考】

http://blog.daocloud.io/principle-of-docker-image/ 深入分析 Docker 镜像原理

https://yq.aliyun.com/articles/68477 Docker镜像原理和最佳实践

Docker实践之02-使用镜像及定制的更多相关文章

  1. docker 实践二:操作镜像

    本篇我们来详细介绍 docker 镜像的操作. 注:环境为 CentOS7,docker 19.03 之前已经说过,容器是 docker 的核心概念之一,所以对应的就需要知道它的使用方法,接下来我们就 ...

  2. Docker实践2:安装Docker及weblogic镜像

    安装Docker 以root登录,运行 vi /etc/yum.repos.d/public-yum-ol6.repo,添加如下段落 [ol6_addons]name=Oracle Linux $re ...

  3. Docker实践,来自沪江、滴滴、蘑菇街架构师的交流分享

    架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享. 第一期主题:容器实践.Docker 作为当前最具颠覆性的开源技术之一,其轻量虚拟化.可移植性是CI/CD,DevOps,微服务的重要 ...

  4. Docker 系列二(操作镜像).

    一.镜像管理 1.拉取镜像 docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] -- Docker 镜像仓库地址 :一般是 域名或者IP[:端口号 ...

  5. Docker 使用Dockerfile构建tomcat镜像

    Dockerfile概念: 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么之前提及的无法重复的问题. ...

  6. Docker实践之01-入门介绍

    目录 一.Docker概述 镜像 容器 仓库 二.安装Docker 1.在CentOS上安装Docker 2.在Ubuntu上安装Docker 3.启动docker 4.建立Docker用户组 5.测 ...

  7. ASP.NET CORE做的网站运行在docker实践

    用VS2017 建立了 DotNet Core 2.2 的网站后,如何转移到 Docker 下运行? 下面分两种方式来实践: 1.直接手动命今行,将本机目录映射进Docker,运行网站.2.制作 Im ...

  8. [转]Docker基础-使用Dockerfile创建镜像

    本文转自:https://www.cnblogs.com/jie-fang/p/7927643.html 1.基本结构 Dockerfile由一行行命令语句组成,并支持以#开头的注释行.例如: # T ...

  9. Docker基础-使用Dockerfile创建镜像

    1.基本结构 Dockerfile由一行行命令语句组成,并支持以#开头的注释行.例如: # This dockerfile uses the ubuntu image # VERSION 2 - ED ...

随机推荐

  1. golang语言示例

    package main import "fmt" /* my first programmer in go */ func fib(n int) int{ if n<2{ ...

  2. 使用 Flask-Cache 缓存给Flask提速

    https://blog.csdn.net/u013205877/article/details/78013289

  3. jeecg入门操作—菜单管理

    一.菜单配置入口 登录jeecg平台,点击系统管理->菜单管理,弹出菜单管理界面 二.配置一级菜单 点击菜单录入 三.配置二级菜单 选中生成的一级菜单,点击菜单录入  四.菜单授权  五.注销系 ...

  4. npm包--rimraf

    含义 rimraf 包的作用:以包的形式包装rm -rf命令,用来删除文件和文件夹的,不管文件夹是否为空,都可删除. 安装 npm install rimraf --save-dev 使用 const ...

  5. vue中watch检测到不到对象属性的变化的解决方法

    watch: { option: { handler(newVal) { console.log(newVal); }, deep: true, immediate: true } }, 需要深层wa ...

  6. asp.net core开源项目

    Orchard框架:https://www.xcode.me/code/asp-net-core-cms-orchard https://orchardproject.net/ https://git ...

  7. C#入门教程源码

    C#入门教程源码 [日期:2019-01-26] 来源:51zxw.net  作者:zhangguofu [字体:大 中 小] 方法一:百度云盘下载地址: 链接:https://pan.baidu.c ...

  8. Oracle 12c CDB PDB 安装/配置/管理

    Oracle安装参考:https://www.cnblogs.com/zhichaoma/p/9288739.html 对于CDB,启动和关闭与之前传统的方式一样,具体语法如下:     STARTU ...

  9. rockchip 3128 平台USB接口鼠标U盘功能调试日记

    2019-04-12 关键词: rk3128 OTG.rk3128外接鼠标U盘.RK外接鼠标U盘 本篇文章是笔者根据自己当前所掌握知识对 rk3128 平台 USB 接口接鼠标实现输入功能调试的一个记 ...

  10. TCP/IP的四元组、五元组、七元组

    TCP/IP的四元组.五元组.七元组 四元组是: 源IP地址.目的IP地址.源端口.目的端口 五元组是: 源IP地址.目的IP地址.协议号.源端口.目的端口 七元组是: 源IP地址.目的IP地址.协议 ...