dongnan
总版主
总版主
  • 粉丝52
  • 发帖数2198
  • 铜币14124枚
  • 威望6134点
  • 银元155个
  • 社区居民
  • 最爱沙发
  • 忠实会员
  • 喜欢达人
  • 原创写手
阅读:2769回复:1

使用 dockerfile 创建镜像

楼主#
更多 发布于:2016-03-15 14:48
开始之前
今天使用一个 **Java项目**的示例,介绍下如何使用 `Dockerfile` 创建一个自定义Java镜像,以及在 `Dockerfile` 中常用的一些指令。


环境描述
容器镜像: openjdk:8-jre
容器系统: debian 8 (jessie)
Docker主机: Ubuntu Server 16.04
CI工具: Jenkins & Maven
项目程序: 编译好的 bms.jar 包


操作步骤
1. 准备 Dockerfile 文件
cat bms/Dockerfile

# bms
FROM openjdk:8-jre
MAINTAINER dongnan

# apt
COPY conf/sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y \
        wkhtmltopdf xvfb \
        && apt-get clean && rm -r /var/lib/apt/lists/*

# env
ENV TZ=Asia/Shanghai \
    LANG=C.UTF-8

# package
COPY src/bms.jar /root/bms.jar

# workdir
WORKDIR /root/

# statement Port
EXPOSE 8080

# cmd
CMD ["java","-jar","/root/bms.jar"]

2. 构建镜像
守护进程读取 `Dockerfile` 文件然后**按照文件中的指令顺序执行**。构建镜像时会一层层构建,前一层是后一层的基础,每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。
docker build -t bms:0.0.1 .
Sending build context to Docker daemon 2.048 mb
# 省略....
Successfully built cd34135ed904
注意: `docker build` 命令最后有一个`.` 表示当前目录,而 `Dockerfile` 就在当前目录,是在**指定上下文路径**。

3. 验证镜像
尝试使用这个镜像创建一个容器,如果容器正常运行说明构建成功。
docker run --name test -tid bms:0.0.1

镜像使用的是**分层存储**容器也是如此,每个容器运行时是**以镜像为基础层**,在其上创建一个当前容器的存储层。
容器运行后修改了容器内的文件,也就是改动了容器的存储层,通过 `docker diff` 命令看到具体的改动。
docker container diff test

C /root            # C 改变
A /root/logs    # A 添加
A /root/logs/bms.log
C /tmp
A /tmp/tomcat-docbase.1383372449962167136.9290

4. 命令帮助
docker build --help

Usage:    docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --cgroup-parent string    Optional parent cgroup for the container
      --compress                Compress the build context using gzip
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int          CPU shares (relative weight)
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                Always remove intermediate containers
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
  -m, --memory bytes            Memory limit
      --memory-swap bytes       Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --network string          Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                Do not use cache when building the image
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --rm                      Remove intermediate containers after a successful build (default true)
      --security-opt strings    Security options
      --shm-size bytes          Size of /dev/shm
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
      --target string           Set the target build stage to build.
      --ulimit ulimit           Ulimit options (default [])


Dockerfile 常用指令
Dockerfile 中每一个指令都会建立一层,上面的示例创建了`9 `层镜像。
* `FROM` 指令用于指定基础镜像,一个有效的 Dockerfile 必须使用 FROM做第一个指令。
* `MAINTAINER` 指令用于设置作者信息。
* `RUN` 指令是用来执行命令的,并将结果提交到当前镜像层。
* `ENV` 指令设置环境变量,无论是后面的其它指令,还是运行时的容器,都可以直接使用这个环境变量。
* `COPY` 指令将从构建上下文目录中 <源> 文件/目录复制到新的一层的镜像内的 <目标> 位置。
* `ADD` 指令和 `COPY` 指令功能基本一致。但是在 COPY 基础上增加了一些功能,例如 ADD会做自动解压工作。
* `WORKDIR` 指令用来指定工作目录(**当前目录**),如该目录不存在则会帮你建立目录。
* `EXPOSE` 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明就会开启这个端口。
* `CMD` 指令用于指定默认容器主进程的启动命令(容器就是进程,在启动容器的时候需要指定所运行的程序及参数)。


内容参考自 <<Docker — 从入门到实践>>
#
欢迎关注微信公众号: 运维录
dongnan
总版主
总版主
  • 粉丝52
  • 发帖数2198
  • 铜币14124枚
  • 威望6134点
  • 银元155个
  • 社区居民
  • 最爱沙发
  • 忠实会员
  • 喜欢达人
  • 原创写手
沙发#
发布于:2016-03-23 18:54
docker dockerfile 中的指令
举个栗子:dockerfile 文件
参考: 1楼。

基本格式
# Comment
指令 参数
指令是不区分大小写的, 然而约定指令是大写的以便区分其他的参数
注释,以#开头表示是注释,例如 # Comment


一些指令
1. FROM 指令
FROM,指令用来构建基础镜像。因此,一个有效的Dockerfile 必须是用FROM做第一个指令
镜像可以是任何有效的镜像,它会很容易从公共存储卡中获取。

FROM,指令可以在 Dockerfile中出现多次创建多个镜像,在用新的FROM之前简单的记录下镜像的id
如果FROM指令没有tag,就假设tag是latest.如果tag不存在,就会输出一个错误信息。

2. MAINTAINER 指令
MAINTAINER,这个指令是允许你设置作者信息

3. RUN 指令
RUN,指令将会在当前镜像执行任何命令并提交结果,提交的镜像的结果,将作为用户 Dockerfile的下一步操作;

4. CMD 指令
#有三种形式:
    CMD "executable","param1","param2"
    CMD ["param1","param2"] (作为ENTRYPOINT默认参数)
    CMD command param1 param2 (像shell一样)
Dockerfile 只能有一个CMD,如果你写了多个CMD,最后那个CMD会生效。

CMD,指令主要给一个容器执行提供默认参数,这些默认值可以是一个?可执行的,或者他们可以省略可执行文件,在这种情况下,你必须指定一个ENTRYPOINT你交号

当shell 中使用执行格式,CMD指令会设置镜像运行的指令,这个功能相当于docker 提交 -run 将会执行在/bin/sh -c
FROM ubuntu
CMD echo "This is a test." | wc -

如果你希望你的容器每次都执行相同的可执行文件,那么你应该考虑使用ENTRYPOINT结合CMD,可以查看ENTRYPOINT.

RUN 与 CMD 的区别
不要混淆RUN 与 CMD,RUN 在构建镜像时执行CMD则是在镜像构建成功后在容器中执行

5. EXPOSE 指令
格式:EXPOSE  [...]
EXPOSE 指令开放端口使用,这个功能相当于运行docker提交 -run '{"PortSpecs": ["", ""]}',相当于docker run -p
注意,多个端口使用空格分隔,例如 EXPOSE 4100 6000 6060 6420 6430

6. ENV 指令  
ENV 指令设置环境变量key对应值value,这个值将会被传递给后边使用的指令,这个功能相当于在指令前面加了=
注意:环境变量会持续到一个镜像的生成

7. ADD 指令
ADD,指令是将复制新文件,并将它们添加到容器的文件系统
必须是一个文件或者目录相对于源目录(也就是构建的环境)或者一个远程文件的URL。

是容器将被复制的目录地址。
所有新创建的文件和目录都是0755权限,uid和gid 0。
如果是目录,将整个目录复制,包含文件的原始数据
如果是压缩文件个事(譬如,gzip、bzip2或者xz),那么它会解压到目录,从URL资源不解压
如果一个目录被复制或者解压,他们都会执行相同的行为tar -x 作为结果的集合
    无论目标路径是否存在
    源的tree内容是否存在
产生冲突的时候会按照2来解决
如果是其它文件类型,她被单独复制连同它的数据。这种情况下,如果以斜线结尾,它就会被认为是一个目录,并将src中的写入/base().
如果不已斜线结尾,它会被认为是一个常规文件,并且的文件会被写入到文件中。
如果不存在,创建连同所有缺失的目录路径

8. ENTRYPOINT 指令
有两种形式:
    ENTRYPOINT ["executable", "param1", "param2"] (像 exec, 首选)
    ENTRYPOINT command param1 param2 (作为shell执行)
Dockerfile 中只能有一个ENTRYPOINT,如果你有多个ENTRYPOINT,则Dockerfile中只能最后一个会被执行
一个ENTRYPOINT会帮你配置容器作为容器的一个可执行文件,也就是说当你指定一个ENTRYPOINT,那么整个容器中都会运行这个可执行文件;

ENTRYPOINT 指令将会被当作一个不会被覆盖的指令参数传给运行的docker,不像CMD,这就是允许参数传递给入口,即docker run  -d 将会通过 -d参数来作为执行入口

你可以指定参数在 ENTRYPOINT JSON数组(如exec执行多个),或者通过使用一个CMD指令语句,这个入口的参数不会被docker run所重写,但是通过指定CMD的参数来重写docker run 参数

像CMD,你可以指定一个ENTRYPOINT的字符串,它将会在/bin/sh -c中执行
FROM ubuntu
ENTRYPOINT wc -l -
例如,Dockerfile的镜像经常会将stdin作为输入("-")或者但列出行数("-l"),如果你像让这个可选,默认情况下你可以使用CMD
FROM ubuntu
CMD ["-l", "-"]
ENTRYPOINT ["/usr/bin/wc"]

示例
ENTRYPOINT ["java","-jar","/root/scf-sign.jar"]

9. VOLUME 指令
格式:VOLUME ["/data"]
VOLUME 指令会创建一个挂载点根据指定的名字和标记挂在外部的主机或者其他容器,更多实例可以查看docker安装说明,共享文档和目录

10. USER 指令
USER daemon
USER质量设置镜像运行时的用户名或者Uid

11. WORKDIR 指令
WORKDIR /path/to/workdir
WORKDIR指令执行工作目录的来执行CMD

12 .COPY指令  
COPY指令和ADD指令功能和使用方式类似。只是COPY指令不会做自动解压工作。

#
欢迎关注微信公众号: 运维录
游客

返回顶部