文章目录

  • 学习内容
  • 命令
    • 拉取镜像
    • 运行容器
    • 列出镜像
    • 查看镜像、容器、数据卷占用空间
    • 虚悬镜像
    • 显示中间层镜像
    • 根据条件列出镜像
    • 只显示镜像id
    • 删除本地镜像
    • 查看镜像历史
  • 定制镜像
    • 定制 `nginx` 的例子:
    • docker build的用法
    • 镜像上下文
    • Dockerfile 命令
      • RUN
      • COPY 复制文件
      • ADD 高级复制文件
      • CMD 容器启动命令
      • ENTRYPOINT 入口点
        • 使用场景一
        • 使用场景二
      • ENV 设置环境变量
      • ARG 参数
      • VOLUME 定义匿名卷
      • EXPOSE 声明端口
      • WORKDIR 指定工作目录
        • 错误脚本书写
      • USER 指定当前用户
      • HEALTHCHECK 健康检查
      • ONBUILD 构建时运行
    • 多阶段构建
    • 镜像的保存

学习内容

  1. 从仓库获取镜像。
  2. 管理本地主机上的镜像。
  3. 介绍镜像实现的基本原理。

命令

拉取镜像

docker pull  [选项]   [DockerRigistry地址[ :端口号] / ] 仓库名 [ :标签]
  • Docker镜像仓库地址: <域名 / IP> [ :端口号 ],默认是 Docker Hub
  • 仓库名:<用户名> / <软件名> 。对于 Docker Hub ,如果不给用户名,默认为 library, 即官方镜像。
docker pull ubuntu:16.04

运行容器

docker  run  -it   --rm  ubuntu:16.04 bash
  • -it-i 是交互式操作,-t 是终端,一般一起使用。
  • --rm:容器退出后随之删除容器,一般不用。
  • ubuntu:16.04:使用镜像。
  • bash: 放在镜像名后面的是命令,指定交互式 shell

列出镜像

docker  image ls

查看镜像、容器、数据卷占用空间

docker  system df

虚悬镜像

1.概念:没有仓库名,也没有标签的的镜像,基本是废弃不用的。
2.查看。

docker image ls -f dangling=true

3.删除所有虚悬镜像。

docker image prune

显示中间层镜像

1.不加 -a 只显示顶层镜像

docker image ls -a

根据条件列出镜像

1.根据仓库名。

docker  image ls ubuntu

2.根据仓库名和标签

docker  image ls  ubuntu:16.04

3.--filter 过滤参数, 简写 -f

docker image ls -f since=mongo:3.2
docker image ls -f  label=com.example.version=0.1

只显示镜像id

1.显示id

docker image ls -q

删除本地镜像

1.删除

docker image  rm [选项]  <镜像1>  [<镜像2> ....]

镜像可以是镜像id、镜像名、摘要

2.配合 ls 删除

docker image rm $(docker image ls -q -f before-mongo :3.2)

查看镜像历史

docker  history  nginx : v2

定制镜像

1.默认的镜像生成文件的名字为 Dockerfile , 可以通过 -f 指定生成文件。
2. FROM scratch 不以任何镜像为基础。

定制 nginx 的例子:

1.新建目录 mynginx,切入到目录。
2.新建 Dcokerfile
3.在 Dockerfile 文件所在的目录执行:

docker build -t nginx:v3  .

4.docker build 命令的格式:

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

docker build的用法

1.直接用 Git repo 构建。

$ docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14

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

2.给定 tar 包构建。

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

3.标准输入读取 Dockerfile 构建,输入为文件的时候。

docker build - < Dockerfile
// 或
cat Dockerfile | docker build -

这种格式没有上下文,不能使用 COPY 指令

4.标准输入压缩包(gzip, bzip2,xz)。

docker build - < context.tar.gz

镜像上下文

Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 APIDocker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实 际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计, 所以 上下文路径 指定打包给远程服务器的一切文件。

Dockerfile 的指令都是在 上下文路径 指定的范围内运行的。如果 上下文路径 写成了当前主机的根目录,那么就会把大当前系统的所有文件传给 Docker 引擎,这是错误的。

Dockerfile 命令

1.Dockerfile 中每一个指令都会建立一层。
2.CMDENTRYPOINTHEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。

RUN

1.两种使用格式:

  • shell 格式:RUN <命令>
  • exec 格式:RUN [ "可执行文件", "参数1", "参数2" ]
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

2.制作redi容器的一个Dockerfile 不合格的写法。

FROM debian:jessie
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install

这里每个 RUN 指令都会新建一层

合格的写法

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \ && mkdir -p /usr/src/redis \&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps

COPY 复制文件

1.两种格式:

  • COPY <源路径> ...<目标路径>
  • COPY [<源路径> ...<目标路径>]

目标路径可以是容器内的绝对路径,也可以是相对于工作目录的相对路径,工作目录可以用 WORKDIR 指令指定。

2.使用通配符格式:

COPY  hom*  /mydir/
COPY  hom?.txt  /mydir/

3.使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间。

ADD 高级复制文件

1.在复制的文件需要自动解压缩的场景下使用:

FROM scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /

2.如果复制的某个压缩文件,不需要解压缩,不要用 ADD 指令。

CMD 容器启动命令

1.命令格式:

  • shell 格式:CMD <命令>
  • exec 格式:CMD ["可执行文件", "参数1", "参数2" ....]。 (使用双引号)
  • 参数列表格式:CMD ["参数1", "参数2" ....]

2.使用 shell 格式,下列命令会被包装成:

CMD echo $HOME

为:

CMD ["sh", "-c", "echo $HOME"]

3.容器中内没有后台服务的概念。对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退 出,容器就失去了存在的意义,从而退出。

命令 CMD service nginx start 被解释成 CMD [ "sh", "-c", "service nginx start"],因此主进程是 sh。那么当 service nginx start 结束了, sh 也就结 束了, sh 作为主进程退出了,自然就会令容器退出。正确的做法是: CMD ["nginx", "-g", "daemon off;"]nginx 为主进程。

ENTRYPOINT 入口点

1.ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

使用场景一

下面查询公网 ip 容器构建脚本:

FROM ubuntu:16.04
RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://ip.cn" ]

生成的容器 myip 是没办法动态指定 curl 的参数 -i 的:

docker run myip -i   // 会报错
docker: Error response from daemon: invalid header field value "oci runtime error: con tainer_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable file not found in $PATH\"\n".

修改脚本为:

FROM ubuntu:16.04
RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

这样构建的容器运行 docker run myip -i 就不会报错。因为 当脚本存在 ENTRYPOINT 指令后, CMD 的内容将会作为参数传给 ENTRYPOINT ,而这里 -i 就是新的 CMD ,因此会作为参数传给 curl ,从而达到了我们预 期的效果。

使用场景二

官方镜像 redis 中:

FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]

entrypoint.sh 脚本的部分内容:

#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then chown -R redis . exec su-exec redis "$0" "$@"
fi
exec "$@"

构建命令 docker run -it redis id

ENV 设置环境变量

1.格式:

  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2> ...
ENV VERSION=1.0 DEBUG=on \ NAME="Happy Feet"

对含有空格的值用双引号括起来
容器运行时,变量也会存在

2.在官方 node 镜像 Dockerfile 中:

ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.ta r.xz" \ && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components= 1 \&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \&& ln -s /usr/local/bin/node /usr/local/bin/nodejs

3.支持的指令:

ADD 、 COPY 、 ENV 、 EXPOSE 、 LABEL 、 USER 、 WORKDIR 、 VOLUME 、 STOPSIGNAL 、 ONBU ILD

ARG 参数

1.格式: ARG <参数名>[=<默认值>]
2.ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。
3.Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。

VOLUME 定义匿名卷

1.格式:

  • VOLUME ["<路径1>", "<路径2>" ...]
  • VOLUME <路径>

2.容器运行时应该尽量保持容器存储层不发生写操作。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂 载,其应用也可以正常运行,不会向容器存储层写入大量数据。

VOLUME /data

运行时可以覆盖这个挂载设 置。比如:

docker run -d -v mydata:/data xxxx

使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

EXPOSE 声明端口

1.格式:EXPOSE <端口1> <端口2>...

WORKDIR 指定工作目录

1.格式:WORKDIR <工作目录路径>
2.使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改 为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。
3. WORKDIR 会改变环境状态并影响以后的层。

错误脚本书写

Docker 是有分层概念的,一个 RUN 指令对于一个分层,那么在 cdecho 之间就不一定是同一个进程执行环境了。

RUN cd /app
RUN echo "hello" > world.txt

USER 指定当前用户

1.格式:USER <用户名>
2.示例:

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

3.如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来 运行某个服务进程,不要使用 su 或者 sudo ,这些都需要比较麻烦的配置,而且在 TTY 缺 失的环境下经常出错。建议使用 gosu

# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/ gosu-amd64" \ && chmod +x /usr/local/bin/gosu \ && gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]

HEALTHCHECK 健康检查

1.格式:

  • HEALTHCHECK [选项] CMD <命令> : 设置检查容器健康状况的命令。
  • HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令。

2.支持选项:

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被 视为失败,默认 30 秒;
  • --retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3 次。

3.HEALTHCHECK [选项] CMD 命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 : 保留,不要使用这个值。

4.示例:

FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s \ CMD curl -fs http://localhost/ || exit 1

5.查看容器状态:

docker container ls

ONBUILD 构建时运行

假设有一个基础镜像 mynode

FROM node:slim
RUN mkdir /app WORKDIR /app
COPY ./package.json /app
RUN [ "npm", "install" ]
COPY . /app/
CMD [ "npm", "start" ]

在构建 mynode 基础镜像时,上面的命令时立即执行比如 copy。如果改成下面的:

FROM node:slim
RUN mkdir /app WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

那么,在引用 mynode 镜像的其他镜像里面,比如下面的:

FROM  mynode

只有在构建上面只有一行的镜像时,mynode 里面带 ONBUILD 的指令才真正的执行。

多阶段构建

FROM golang:1.9-alpine as builder  // as 第一阶段
RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld/
RUN go get -d -v github.com/go-sql-driver/mysql
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest as prod    // as 第二阶段
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/go/helloworld/app .
CMD ["./app"]

镜像的保存

$ docker image ls alpine
REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest baa5d63471ea 5 weeks ago 4.803 MB$ docker save alpine | gzip > alpine-latest.tar.gz$ docker load -i alpine-latest.tar.gz
Loaded image: alpine:latest

[1] Docker技术入门与实战
[2] Docker 官方镜像 Dockerfile
[3] Dockerfile 最佳实践文档

Docker 使用镜像相关推荐

  1. 【Docker】registry部署docker私有镜像仓库

    Docker Hub作为Docker默认官方公共镜像仓库,但是如果我们不想使用怎么办,第一我们可以替换默认镜像仓库为我们国内的一些镜像仓库,第二就是如我们自己搭建一个自己的私有镜像仓库,官方也提供do ...

  2. docker制作镜像篇(基于容器)

    docker制作镜像可以有两种方式: 一.基于容器(使用busybox制作http镜像) 1.首先运行一个容器 2.在容器当中配置自己的http,添加web目录,增加主页文件等. 3.查看原busyb ...

  3. Centos7制作docker初始镜像

    Centos7用febootstrap制作docker初始镜像包 使用工具:febootstrap 下载地址:http://down.51cto.com/data/2330414 使用命令: febo ...

  4. Docker:镜像操作和容器操作

    镜像操作 列出镜像: $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE hello-world latest 0a6b ...

  5. docker ubuntu镜像_Docker 入门指南 | Linux 中国

    该教程包含了如何创建一个新的 Docker 容器,如何运行该容器,如何从现有的 Docker 容器中创建自己的 Docker 镜像等 Docker 的一些基础知识.操作.-- Sk 在我们的上一个教程 ...

  6. docker java镜像_Docker JDK镜像

    Docker jdk镜像 说明 使用alpine-glibc作为基础镜像 JAVA JDK/JRE以1.8为基准 下载文件 创建Dockerfile JDK FROM docker.io/jeanbl ...

  7. Docker Hub 镜像加速器

    感谢您的阅读,本文由 杨斌的博客 版权所有. 如若转载,请注明出处:杨斌的博客(y0ngb1n.github.io/a/docker-re-) 本文首发于 GitHub Gist:gist.githu ...

  8. Docker 制作镜像

    docker镜像制作的两种方法: 1,基于docker commit 制作镜像 2,基于dockerfile制作镜像,为主流镜像制作方式. [基于基础镜像定制后,使用commit制作自定义镜像] 1, ...

  9. Docker的镜像使用

    Docker的镜像使用 一.获取Docker镜像 1.Docker仓库 2.查找搜索镜像 3.查看本地的docker镜像 4.下载镜像到本地 5.查看docker信息 ①.查看docker数据存放目录 ...

  10. Docker之镜像、容器、仓库概念

    Docker镜像 操作系统分为内核和用户空间.对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持.而 Docker 镜像(Image),就相当于是一个 root 文件系 ...

最新文章

  1. (C++)寻找1-100以内所有素数,复杂度为O(nsqrt(n))与O(nloglogn)的两种方法
  2. python程序员工作怎样-怎样才能成为一名Python程序员
  3. 玩转嵌入式,且看痞子衡
  4. 前端学习(3288):object.define
  5. 让女生觉得坏透了的聊天方式有哪些?
  6. centos下 将(jgp、png)图片转换成webp格式
  7. nlp n-gram_NLP中的单词嵌入:一键编码和Skip-Gram神经网络
  8. CRIO脱机计算机工作,LabVIEW和cRIO入门
  9. http://baiy.cn/doc/cpp/inside_exception.htm#栈回退(Stack_Unwind)机制
  10. 机械硬盘如何克隆至固态硬盘,如何把硬盘系统克隆到固态硬盘
  11. windows 无法停止ics_Win10系统ICS服务启动后停止怎么办
  12. 带有神经网络的梯度消失(Vanishing gradients with RNNs)
  13. 史上最全的HTML、CSS知识点总结,浅显易懂。适合入门新手
  14. V831体验—烧录系统
  15. python 升级setuptools_PIP无法升级setuptools
  16. 除甲醛产品哪个好?除甲醛产品十大品牌第一名
  17. IOS开发 - 网络总结(一)
  18. 2013 duilib入门简明教程 -- 总结 (20)
  19. 2022-2027年中国醋纤滤棒行业运行态势及未来发展趋势预测报告
  20. 【404 App】2.0全新版本正式来袭之ME模块。

热门文章

  1. 渐进式神经网络结构搜索技术(Progressive Neural Architecture Search)(2018年最强最智能的图像分类)详解
  2. 中英文对照版本-小伯利恒之歌-O Little Town of Bethlehem 史茵茵-音乐河86
  3. Comparator::compare设定排序的升序 降序
  4. 卡尔曼滤波,最最容易理解的讲解.找遍网上就这篇看懂了.
  5. 公众号推送长图最佳尺寸_公众号长图文排版技巧
  6. Socket中EndPoint只获取ip,不要port
  7. Jasperreports6.4.1+Jaspersoft studio6.4.1进行报表开发实战教程-PDF中文显示
  8. 推荐 :机器学习x环境科学:实时预测下一小时的降雨
  9. 计算机科学与技术专业代码是080901还是081200?
  10. git refs/for 命令