Dockerfile基本使用及打包镜像

镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础。我们之前的例子都是使用来自docker hub的镜像,直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。

镜像的定制就是定制每一层所添加的配置、文件。如果可以吧每一层修改、安装、构建、操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是dockerfileDockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令 构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

DockerFile基本关键词及解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
FROM scratch #制作base image 基础镜像,尽量使用官方的image作为base image
FROM centos #使用base image
FROM ubuntu:14.04 #带有tag的base image

LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
LABEL maintainer=“yc_uuu@163.com"

#对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
RUN yum update && yum install -y vim \
Python-dev #反斜线换行
RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”

WORKDIR /root #相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd
WORKDIR /test #如果没有就自动创建
WORKDIR demo #再进入demo文件夹
RUN pwd #打印结果应该是/test/demo

ADD and COPY
ADD hello / #把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录
ADD test.tar.gz / #添加到根目录并解压

WORKDIR /root
ADD hello test/ #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
COPY hello test/ #等同于上述ADD效果

ADD与COPY
- 优先使用COPY命令
-ADD除了COPY功能还有解压功能
添加远程文件/目录使用curl或wget

ENV #环境变量,尽可能使用ENV增加可维护性
ENV MYSQL_VERSION 5.6 #设置一个mysql常量
RUN yum install -y mysql-server=“${MYSQL_VERSION}”
------这里需要稍微理解一下了-------中级知识---先不讲
VOLUME and EXPOSE
存储和网络

RUN and CMD and ENTRYPOINT
RUN:执行命令并创建新的Image Layer
CMD:设置容器启动后默认执行的命令和参数
ENTRYPOINT:设置容器启动时运行的命令

Shell格式和Exec格式
RUN yum install -y vim
CMD echo ”hello docker”
ENTRYPOINT echo “hello docker”

Exec格式
RUN [“apt-get”,”install”,”-y”,”vim”]
CMD [“/bin/echo”,”hello docker”]
ENTRYPOINT [“/bin/echo”,”hello docker”]


通过shell格式去运行命令,会读取$name指令,而exec格式是仅仅的执行一个命令,而不是shell指令
cat Dockerfile
FROM centos
ENV name Docker
ENTRYPOINT [“/bin/echo”,”hello $name”]#这个仅仅是执行echo命令,读取不了shell变量
ENTRYPOINT [“/bin/bash”,”-c”,”echo hello $name"]

CMD
容器启动时默认执行的命令
如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略
如果定义多个CMD,只有最后一个执行

ENTRYPOINT
让容器以应用程序或服务形式运行
不会被忽略,一定会执行
最佳实践:写一个shell脚本作为entrypoint
COPY docker-entrypoint.sh /usr/local/bin
ENTRYPOINT [“docker-entrypoint.sh]
EXPOSE 27017
CMD [“mongod”]

[root@master home]# more Dockerfile
FROm centos
ENV name Docker
#CMD ["/bin/bash","-c","echo hello $name"]
ENTRYPOINT ["/bin/bash","-c","echo hello $name”]

示例之打包flask程序

准备几行flask代码

1
2
3
cd /tmp
touch app.py
vim app.py

写入以下代码

1
2
3
4
5
6
7
8
#coding:utf8
from flask import Flask
app=Flask(__name__)
@app.route('/')
def hello():
return "hello docker, Im from Flask!!! Bye"
if __name__=="__main__":
app.run(host='0.0.0.0',port=8080)

准备Dockerfile文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
touch Dockerfile
vim Dockerfile

# 写入以下代码:
# 基础镜像
FROM python:2.7
# 容器镜像元信息,作者
LABEL maintainer="tony yu<tony@visas.to>"
# 运行命令安装flask
RUN pip install flask
# 复制宿主机上的app.py文件到容器镜像中的/app文件夹
COPY app.py /app/
# 切换容器镜像中的目录至/app
WORKDIR /app
# 打开容器的8080端口,供宿主机使用
EXPOSE 8080
# cmd命令,使用python执行app.py
CMD ["python","app.py"]

构建镜像image

命令行中的.代表的是当前目录,会在当前目录中找到一个名为Dockerfile的文件去执行

1
docker build -t tonyu/flask-hello .

查看是否已安装镜像

1
2
3
root@Tony-PC:/tmp# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tonyu/flask-hello latest b7ac47e3f338 About a minute ago 890MB

运行镜像

1
docker run -d -p 8008:8080 tonyu/flask-hello

查看正在运行的镜像

可以看到我们的镜像已经正常在运行

1
2
3
4
root@Tony-PC:/tmp# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10c69359fda0 tonyu/flask-hello "python app.py" 2 minutes ago Up 2 minutes 0.0.0.0:8008->8080/tcp musing_lehmann

导出或上传该镜像

我们可以参考导出导入镜像进行该操作