在介绍 Docker 具体的操作前,先简要复习下 Docker 的架构,这样可以更好地帮助我们理解 Docker 中的各个命令。

首先我们一直对 Docker 这个叫法就有些误解,Docker 其实指代的是用于开发,部署,运行应用的一个平台。平常中说的 Docker 准确来说是 Docker Engine.

Docker Engine 是一个 C/S 架构的应用。其中主要的组件有:

  • Docker Server:长时间运行在后台的程序,就是熟悉的 daemon 进程.
  • Docker Client: 命令行接口的客户端。
  • REST API: 用于和 daemon 进程的交互。

我们通过给 Docker Client 下发各种指令,然后 Client 通过 Docker daemon 提供的 REST API 接口进行交互,来让 daemon 处理编译,运行,部署容器的繁重工作。 大多数情况下, Docker Client 和 Docker Daemon 运行在同一个系统下,但有时也可以使用 Docker Client 来连接远程的 Docker Daemon 进程,也就是远程的 Server 端。

清楚了 Docker 的简单架构,就可以了解下具体的命令了。

Docker 镜像构建指令

指令1:构建镜像

docker build [OPTIONS] PATH | URL | -

Docker 构建镜像的上下文。

这里的上下文指的就是命令的最后一个参数 PATH | URL| -,具体来说就 docker build . 中的 . 很多人以为这个 . 是 DockerFile 的位置,其实不然,准确来说是构建上下文的位置。前面说到 Docker 是 C/S 架构,在 Client 端下发具体的命令,在 Server 端(Daemon)执行具体的内容。这也就意味着,构建镜像的过程其实是在 Server 端完成的。而上下文的出现,就是为了把需要的内容传递给 Server,这也就为什么在每次构建时都能看到这样一句话。

[root@localhost python_shell]# docker build --rm -t temp/python-test .
Sending build context to Docker daemon 4.608kB

这里的 Sending 其实就是把本地 Client 端的文件内容,拷贝到 Server 端。而许多初学者,在 DockerFile 中写出了 COPY /opt/xxxx /app 这样的话,其实就是没有理解上下文的概念,并不知道在 Server 端是没有 opt/xxxx 的文件的。

还有的人将 Docker File 放在硬盘根目录执行,殊不知,这样会将根目录所有的文件都拷贝到 Server 端,造成构建极其缓慢。

Options 常用参数:

  • -t: 打包出镜像的名称及标签,通常写法为 name:tag
  • --rm: 构建成功后,删除中间产生的容器。
  • --force-rm=true: 无论是否构建成功,都删除中间产生的容器
  • --no-cache: 构建镜像时不使用缓存。
  • -f: 指定 DockerFile 的路径
docker build --no-cache --force-rm -t --no-cache local/centos7:v1 .

DockerFile 指令及编写规范

指令1:指定基础镜像

通过 FROM 来制定基础镜像,命令很简单,但有一点需要注意的是,一定确切指定基础镜像的版本,而不是写成 latesst, 因为随着时间推移,官方的最新镜像都会一直更新,这样就会造成无法构建的情况。

FROM centos:7 # That's perfect!
FROM centos:latest # That's so bad!

指令2:容器中执行命令

RUN 命令用于在容器中执行命令行的命令。一般有两种写法:

  • shell 形式:

RUN 后面直接跟 shell 命令就可以了。切记,在 shell 形式下,不要把命令拆成多行 RUN。因为每一次的 RUN 都会构建一层新的镜像,保存了很多没有用的运行信息。而且 Union FS 是由最大层数限制的。所以尽量将命令合成一行。

RUN yum -y install httpd; yum clean all; systemctl enable httpd.service # That's perfect!

RUM yum -y install httpd / # Another perfect solution!
yum clean all /
systemctl enable httpd.service RUN yum -y install httpd # That's so bad!
RUN yum clean all;
....

还有一点需要注意,把构建时没用的依赖包想着清空。否则的话,随着镜像的重复构建,保存了大量的没有信息。

  • exec 写法

exec 写法更像函数调用中的格式。

RUN ["可执行文件", "参数1", "参数2"]

RUN ["yum", "-y", "install", "httpd"]

指令3:设置工作目录

WORKDIR 用于改变各层的工作目录(也就是进入容器内的默认目录),如果指定的目录不存在就会创建它。工作目录在构建过程中,可以被各层都访问到。

WORKDIR /src

指令4:设置匿名卷

在容器运行时,尽量对容器的存储层不进行写操作,对于像数据库中这样动态的数据文件应该用 VOLUME 来保存。而在 DockerFile VOLUME 可以将目录指定为匿名卷。这样在运行时,如果没有挂载指定的目录,并不会像容器的存储层写入数据,保证存储层的无状态化。

VOLUME /data

开启 Systemd Centos7 镜像

官方 Centos7 的镜像已经包含了 systemd 的功能,只是没有开启。这里只需要以其为基础镜像,打开 systemd 的功能即可。需要注意的是,打开 systemd 需要在运行时开启特权以挂载 Cgroup 等内容。

编写 DockerFile

[root@localhost docker_images]# cat Dockerfile
FROM centos:7 ENV container docker RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
  • VOLUME 指定了匿名目录,不会在存储层保存该目录的内容,适用于动态变化等持久性文件。
  • CMD 保证容器启动时开启 systemd

打包镜像

 docker build --rm -t local/c7-systemd .
  • --rm: 表示删除打包时临时的容器

运行镜像

docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro local/c7-systemd
  • --privileged: 给予容器特殊的权限,来挂载 Cgroup 等。

Httpd 镜像

下面基于上面开启 systemd 的镜像为基础,打包 Httpd 镜像。

编写 DockerFile

FROM local/c7-systemd

RUN yum -y install httpd; yum clean all; systemctl enable httpd.service

EXPOSE 80
  • 下载依赖包后,删除没有用的内容,是编写 DockerFile 好习惯。

编译 DockerFile

docker build --rm -t local/c7-systemd-httpd .

运行 Container

docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-p 80:80 local/c7-systemd-httpd

在下载依赖时出现网络问题,请查看 Docker 代理 这篇文章。

Python 镜像

有时我们需要在容器中运行 python 脚本,下面来打包类似的镜像。在下载需要的依赖时,通常的服务器并没访问公网的能力,这时需要为容器配置配置代理,在下载依赖后,有时由于代理的原因,导致内部的服务器无法访问,这时可以再将设置的代理清空。

创建文件

注意,这里的文件要和 DockerFile 在同级目录下。

# 创建 requirements 文件保存依赖
[root@localhost home]# cat python_shell/requirements.txt
requests==2.21.0 # 编写 Python 脚本
[root@localhost home]# cat python_shell/success.py
print("python Running", "!");

编写 DockerFile

FROM python:3.6.8

# set proxy
ENV MY_PROXY_URL="http://173.39.112.117:80"
ENV HTTP_PROXY=$MY_PROXY_URL \
HTTPS_PROXY=$MY_PROXY_URL \
FTP_PROXY=$MY_PROXY_URL \
http_proxy=$MY_PROXY_URL \
https_proxy=$MY_PROXY_URL \
ftp_proxy=$MY_PROXY_URL WORKDIR /src COPY . . RUN ["pip", "install", "--no-cache-dir", "-r", "./requirements.txt"] # clear the proxy
ENV MY_PROXY_URL=
ENV HTTP_PROXY=$MY_PROXY_URL \
HTTPS_PROXY=$MY_PROXY_URL \
FTP_PROXY=$MY_PROXY_URL \
http_proxy=$MY_PROXY_URL \
https_proxy=$MY_PROXY_URL \
ftp_proxy=$MY_PROXY_URL CMD ["python", "./success.py"]

打包镜像

docker build --rm -t temp/python-test .

运行镜像

[root@localhost home]# docker run temp/python-test
python Running !

参考

docker-overview

docker-centos-image

docker-python-image

https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/

dockerfile_best-practices

docker-chinese-reference

# 通过 DockerFile 打包镜像的更多相关文章

  1. Kbengine游戏引擎-【5】用Dockerfile打包镜像kbengine

    本文是以docker为例,以ubuntu 16.04做基础镜像 kengine 1.0.0 用supervisor来管理启动 先放下目录结构图: kb--里面放的是kbengine的编译后的引擎以及d ...

  2. 利用dockerfile定制镜像

    利用dockerfile定制镜像 镜像的定制就是定制每一层所添加的配置.文件.如果可以吧每一层修改.安装.构建.操作的命令都写入到一个脚本,用脚本来构建.定制镜像,这个脚本就是dockerfile. ...

  3. Docker Dockerfile 定制镜像(转)

    转自: https://yeasy.gitbooks.io/docker_practice/ 及 https://blog.csdn.net/wo18237095579/article/details ...

  4. SpringBoot 部署 docker 打包镜像

    SpringBoot 部署 docker 打包镜像 环境: 1.代码编写工具:IDEA 2.打包:maven 3.docker 4.linux 7.JDK1.8 8.Xshell 9.Xftp 第一步 ...

  5. Docker Dockerfile 定制镜像

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

  6. docker(常见调试技巧):docker打包镜像调试技巧

    写Dockerfile可以先不指定CMD.ENTRYPOINT等启动命令,只要拷贝就好了 如下: # Dockerfile for basic-app-client # Build with: # d ...

  7. Docker用Dockerfile定制镜像

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

  8. docker将jar打包镜像文件

    1.首先需要编写dockerfile文件,通过dockerfile文件将jar包打成镜像 编写dockerfile文件 # 定义父镜像 FROM java:8 # 维护者信息 MAINTAINER c ...

  9. docket打包镜像内部报错

    临时记录,后面再完善 对于前端docker一般不太熟悉,当我们想要打包镜像的时候会去找教程,我按着教程去打包一个使用KOA框架搭建的node服务. 这是一个 koa + ts + pm2的项目 结果出 ...

随机推荐

  1. [vsCode实践] 实践记录

    [vsCode实践] 实践记录 版权2019.5.1更新 Q1:代码中涉及到操作本地文件时,相对路径总是不对 操作本地文件时,路径方式有两种 相对路径 例如:代码文件所在路径/Users/tp0829 ...

  2. 2017 ACM-ICPC亚洲区域赛北京站J题 Pangu and Stones 题解 区间DP

    题目链接:http://www.hihocoder.com/problemset/problem/1636 题目描述 在中国古代神话中,盘古是时间第一个人并且开天辟地,它从混沌中醒来并把混沌分为天地. ...

  3. 「Luogu P3931」SAC E#1 - 一道难题 Tree 解题报告

    圆原题面 我环顾四周,发现大佬们的写法都好高端! 比较差劲的我,只能交上一份DFS的题解 思路: DFS(当然了,其他算法也行) 要想切断叶子节点到根节点的连接 就是在叶子节点和根节点之间砍掉一条边 ...

  4. 小小知识点(十四)——Adobe photoshop cc 2018中简单抠图的一些基本操作

    一 如何抠图 1. 右键弹出选择工具,随后鼠标左键选择快速选择工具 2.通过点击鼠标,选择想要的区域: Alt+鼠标右键  左右拖动鼠标可调整画笔大小 Alt+鼠标滑轮,可放大或缩小画布大小 ctrl ...

  5. 浅谈Java三大特性之封装

    目录 前言 好处 介绍(实现方式) 示例 小结 感谢阅读!!! 三大特性之浅谈封装 前言 英语:Encapsulation--封装,包装. 面向对象的封装与真实世界的目的是一样的.封装能够使外部访问者 ...

  6. Java网络编程系列之TCP连接状态

    1.TCP连接状态 LISTEN:Server端打开一个socket进行监听,状态置为LISTEN SYN_SENT:Client端发送SYN请求给Server端,状态由CLOSED变为SYN_SEN ...

  7. Qt5学习(1)

    1. In Qt, if you want to apply styles to the main window  itself, you must apply it to  its central ...

  8. Collection 的子类 List

    List集合的一些使用方法: 一. 声明集合: List<String> list = new ArrayList<String>(); 二.往集合里面添加元素 list.ad ...

  9. 解决elment 动态多选框组(el-checkbox-group)无法设置默认值问题

    <el-checkbox-group v-model="form.showProperty"> <el-checkbox v-for="(item,id ...

  10. Kettle中JavaScript内置函数说明

    本文链接:https://blog.csdn.net/u010192145/article/details/102220563 我们在使用JavaScript组件的时候,在左侧核心树对象栏中可以看到K ...