Docker教程:自动镜像构建dockerfile

http://blog.csdn.net/pipisorry/article/details/50805379

Docker透过Dockerfile来记录建立Container映象文件的每一个步骤,可以将建立应用程序执行环境的过程和配置参数,完整地记录下来。开发人员和维运人员之间可以利用Dockerfile来沟通对执行环境的讨论。

甚至结合版本控制服务如GitHub,可以让Dockerfile具备版本控制功能,能将基础架构程序化(Infrastructure as code)来管理。

构建自定义的镜像

Docker能自动创建镜像,构建自定义的镜像,有两种方法:

1、使用docker commit 命令

关于commit命令,其实就是使用docker run -i -t XXX /bin/bash 进入容器的交互界面,进行各种操作后,再将这个容器通过提交命令提交上去来达到目的。

2、使用Dockerfile

这里介绍dockerfile方法,因为使用Dockerfile构建拥有比提交命令更高的灵活性和可维护性。所以这里也是通过Dockerfile来构建这个自定义的镜像。

易于自动化的命令

Dockerfile包含创建镜像所需要的全部指令。基于在Dockerfile中的指令,我们可以使用Docker build命令来创建镜像。通过减少镜像和容器的创建过程来简化部署。

Dockerfile支持的语法命令如下:INSTRUCTION argument。指令不区分大小写。但是,命名约定为全部大写。在文本文件或Dockerfile文件中这些命令的顺序就是它们被执行的顺序。

皮皮blog



Dockerfile命令

如果一个镜像存在相同的父镜像和指令(除了ADD),Docker将会使用镜像而不是执行该指令,即缓存。为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。

使用 # 作为注释,但是lz试过,注释很多时候必须单独成行,否则如果接在目录后面,会出现No such file or directory报错。


所有Dockerfile都必须以FROM命令开始。 

FROM命令会指定镜像基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像(CentOS和Ubuntu有些命令可是不一样的)。FROM命令可以多次使用,表示会创建多个镜像。

具体语法如下:FROM <image name> 或者:FROM <image>:<tag>

1. MAINTAINER用来指定维护者的姓名和联系方式。MAINTAINER <author name>

更改MAINTAINER指令会使Docker强制执行RUN指令来更新apt,而不是使用缓存。

2. RUN:在shell或者exec的环境下执行的命令。RUN指令会在新创建的镜像上添加新的层面,接下来提交的结果用在Dockerfile的下一条指令中。每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。也就是说RUN命令会在上面FROM指定的镜像里执行任何命令,然后提交(commit)结果,提交的镜像会在后面继续用到。

RUN命令等价于:

docker run image command docker commit container_id

格式为 RUN <command> 或 RUN ["executable", "param1", "param2"]

前者将在shell终端中运行命令,即 /bin/sh -c ;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"] 。

3. ADD:复制文件指令。它有两个参数<source>和<destination>。

语法如下:ADD 《src》 《destination》

<src> 是相对被构建的源目录的相对路径!,可以是文件或目录的路径,也可以是一个远程的文件url。<dest> 是container中的绝对路径

4. CMD:提供了容器默认的执行命令。 Dockerfile只允许使用一次CMD指令。多个只有最后一个指令生效。

支持三种格式
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;

5. EXPOSE:指定容器在运行时监听的端口。

语法如下:EXPOSE <port> [<port>...]

比如memcached使用端口 11211,可以把这个端口暴露在外,这样容器外可以看到这个端口并与其通信。

Note: <port>后面不能接空格或者注释什么的,否则会报错:EXPOSE 22 INFO[1063] Invalid containerPort:

Docker的核心概念是可重复和可移植。镜像应该可以运行在任何主机上并且运行尽可能多的次数。

在Dockerfile中你有能力映射私有和公有端口,但是你永远不要通过Dockerfile映射公有端口。通过映射公有端口到主机上,你将只能运行一个容器化应用程序实例。(运行多个端口不就冲突啦)
#private and public mapping
EXPOSE 80:8080
#private only
EXPOSE 80
如果镜像的使用者关心容器公有映射了哪个公有端口,他们可以在运行镜像时通过-p参数设置,否则,Docker会自动为容器分配端口。
切勿在Dockerfile映射公有端口。

[计算机端口]

6. ENTRYPOINT:配置给容器一个可执行的命令,这意味着在每次使用镜像创建容器时一个特定的应用程序可以被设置为默认程序。同时也意味着该镜像每次被调用时仅能运行指定的应用。类似于CMD,Docker只允许一个ENTRYPOINT,多个ENTRYPOINT会抵消之前所有的指令,只执行最后的ENTRYPOINT指令。

ENTRYPOINT 命令设置在容器启动时执行命令,也就是配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。

# cat Dockerfile
FROM ubuntu
ENTRYPOINT echo "Welcome!"

# docker run 62fda5e450d5
Welcome!
两种语法格式,一种就是上面的(shell方式):ENTRYPOINT cmd param1 param2 ...
第二种是 exec 格式:ENTRYPOINT ["cmd", "param1", "param2"...]

USER 命令:镜像正在运行时设置一个UID。语法如下:USER <uid>
比如指定 memcached 的运行用户,可以使用上面的 ENTRYPOINT 来实现:ENTRYPOINT ["memcached", "-u", "daemon"]
更好的方式是:
ENTRYPOINT ["memcached"]
USER daemon

ENTRYPOINT echo这个运行时一直调用不出bash命令,显示过后就退出了,不知道为嘛?所以lz在dockerfile中注释了这一句。

7. WORKDIR:指定 RUNCMDENTRYPOINT命令的工作目录。语法如下: WORKDIR /path/to/workdir

8. ENV:设置环境变量。它们使用键值对,增加运行程序的灵活性。

语法如下:ENV <key> <value>

设置了后,后续的RUN命令都可以使用
使用此dockerfile生成的image新建container,可以通过 docker inspect 看到这个环境变量:
root@pika:~# docker inspect 49bfc7a9817f
也可以通过在docker run时设置或修改环境变量:
docker run -i -t --env name="pi" ubuntu:newtest /bin/bash

9. VOLUME:授权访问从容器内到主机上的目录。用于containers之间共享数据

语法如下:VOLUME ["/data"]

[Docker 2 -- 关于Dockerfile]

[Dockerfile指令总结]

[Dockerfile reference]

Dockerfile示例

/media/pi/files/mine/python_workspace/DockerEnv/dockerfile

#python3 development environment
FROM ubuntu:14.04
MAINTAINER pi "[email protected]"
#ENTRYPOINT echo "python3 development environment\n"


# 更新源,原生ubuntu镜像中的下载源速度太慢,然而下面这个源并不是最新的,居然没有python3-pip!!!
#RUN echo "deb http://mirrors.163.com/ubuntu precise main universe" > /etc/apt/sources.list
#RUN echo "deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse" > /etc/apt/sources.list
RUN apt-get update


#安装ssh server进行远程操控
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
# 设置root ssh远程登录密码
RUN echo "root:249784435" | chpasswd
# 容器需要开放SSH 22端口,以使外部能够访问容器内部
EXPOSE 22


#常用安装
#软件冲突,要先将vim-common卸载,再装vim
RUN apt-get remove -y vim-common
RUN apt-get install -y vim
RUN apt-get install -y git
RUN apt-get install -y wget


#安装python3开发环境
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN ln -sf /usr/bin/python3.4 /usr/bin/python
RUN ln -sf /usr/bin/pip3 /usr/bin/pip


#apt-get安装python3拓展包(有的包pip安装会出错)
RUN apt-get install -y python3-numpy
RUN apt-get install -y python3-scipy
#extra packages installed : python3-six ... + python3-numpy
RUN apt-get install -y python3-matplotlib
#extra packages installed : python3-dateutil python3-nose  python3-pil python3-pyparsing python3-tk python3-pytz  python3-tornado ... + python3-numpy
RUN apt-get install -y python3-pandas
RUN apt-get install -y mysql-server mysql-client


#pip安装python3拓展包(有的只能pip安装)
ADD requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt

[Dockerfile reference]

[python_webapp/blob/master/Dockerfile]

[Docker制作一个支持SSH终端登录的镜像]

[Docker搭建一个JAVA Tomcat运行环境]

皮皮blog


构建自定义ubuntu镜像

使用Dockerfile构建镜像命令

docker build [options] PATH | URL
额外选项,如:
--rm=true表示构建成功后,移除所有中间容器
--no-cache=false表示在构建过程中不使用缓存

-t   给该镜像赋予一个tag,用以将来的调用与搜索 

.   表示调用当前目录的Dockerfile

$cd /media/pi/files/mine/python_workspace/DockerEnv

$docker build -t py-ubuntu .

Docker教程:自动镜像构建dockerfile_第1张图片

之后可以通过用"docker images"命令查看镜像

ssh后台容器长时间运行

不至于运行了几秒后容器会自动退出
docker run -d -p 22 -p 80:8080 python_ubuntu /usr/sbin/sshd -D
其中:

-d  表示使容器在后台运行

-p      指定端口设置,这里ubuntu容器内运行着的SSH Server占用22端口

-p 80:8080  表示端口的映射,映射主机端口到容器,方便外部访问容器内服务,主机端口80可以省略,省略表示把容器端口8080映射到一个动态端口。ubuntu将会以8080端口运行ssh,但对外(容器外)映射的端口为80。
/usr/sbin/sshd   表示启动ssh服务
-D     表示容器长时间运行,不至于几秒后退出
之后可以用docker ps命令查看容器是否成功运行,发现容器被随机赋予了一个****SSH连接端口号。

在主机用ssh命令来登录这个容器:

ssh [email protected] -p ****

Note: 启动镜像实例的时候,指定了 -p 80:8080,容器开放8080端口,映射到宿主机端口就是80。知道宿主机IP地址,那就可以自由访问容器了。在宿主机上,通过curl测试一下即可:curl http://192.168.*.*。当然,你也可以使用浏览器访问啦。真实情况,可能不会让SSH直接对外开放80端口,一般都会位于nginx/apache或者防火墙的后面。

最佳实践:注意事项

当构建镜像时使用可理解的标签,以便更好地管理镜像;
避免在Dockerfile中映射公有端口;
CMD与ENTRYPOINT命令请使用数组语法。

在使用apt-get安装软件时,需要加上"-y"的参数,如果不指定-y参数的话,apt-get命令会进入交互模式,需要用户输入命令来进行确认,但在docker环境中是无法响应这种交互的。所以就会造成安装中断这种问题。

如果安装了ssh,chpasswd方法给ssh添加root用户登录密码为123456。"chpasswd"可以批量的为ssh添加以"username:passwd"为格式的用户与密码。可以将username:passwd批量的写在一个txt文件中,然后使用xxx.txt chpasswd方法为ssh批量添加用户。

from: http://blog.csdn.net/pipisorry/article/details/50805379

ref:Docker 4 -- 总结


你可能感兴趣的:(docker,dockerfile)