在Docker的运用中,从下载镜像,启动容器,在容器中输入命令来运行程序,这些命令都是手工一条条往里输入的,无法重复利用,而且效率很低。所以就需要一 种文件或脚本,我们把想执行的操作以命令的方式写入其中,然后让docker读取并分析、执行,那么重复构建、更新将变得很方便,所以Dockerfile就此诞生了。Docker提供了Dockerfile作为构建Docker镜像脚本,避免人们一行一行的输入,真是善莫大焉。Dockerfile脚本可以做到随时维护修改,即可以分享,更有利于在模板化,更不用说传输了,好处那是一大箩筐!下面就详细介绍下Dockfile的使用:

Dockfile是一种被Docker程序解释的脚本,它由一条条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译成真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。

总的来说:
Dockerfile分为四部分:基础镜像信息、镜像创建者信息、镜像操作指令、容器启动执行指令。
一开始必须要指明所基于的镜像名称,接下来一般会说明镜像创建者信息。后面则是镜像操作指令

一、Dockerfile的书写规则及指令使用方法
Dockerfile的指令是忽略大小写的,建议使用大写,使用 # 作为注释,每一行只支持一条指令,每条指令可以携带多个参数。
Dockerfile的指令根据作用可以分为两种:构建指令和设置指令。
构建指令用于构建image,其指定的操作不会在运行image的容器上执行;
设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行。

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
1)FROM(指定基础image)
构建指令,必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。
FROM命令告诉docker我们构建的镜像是以哪个(发行版)镜像为基础的。第一条指令必须是FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令。
 
该指令有两种格式:
FROM <image> 
指定基础image为该image的最后修改的版本。或者:
 
FROM <image>:<tag> 
指定基础image为该image的一个tag版本。
 
RUN后面接要执行的命令,比如,我们想在镜像中安装vim,只需在Dockfile中写入 RUN yum install -y vim
 
2)MAINTAINER(用来指定镜像创建者信息)
构建指令,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。
 
格式:
MAINTAINER <name> 
 
3)RUN(安装软件用)
构建指令,RUN可以运行任何被基础image支持的命令。如基础image选择了ubuntu,那么软件管理部分只能使用ubuntu的命令。
 
该指令有两种格式:
RUN <command>  
RUN ["executable""param1""param2" ... ] 
 
4)CMD(设置container启动时执行的操作)
设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。
 
该指令有三种格式:
CMD ["executable","param1","param2"]
CMD command param1 param2
 
当Dockerfile指定了ENTRYPOINT,那么使用下面的格式:
CMD ["param1","param2"]
 
其中:
ENTRYPOINT指定的是一个可执行的脚本或者程序的路径,该指定的脚本或者程序将会以param1和param2作为参数执行。
所以如果CMD指令使用上面的形式,那么Dockerfile中必须要有配套的ENTRYPOINT。
 
5)ENTRYPOINT(设置container启动时执行的操作)
设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。
 
两种格式:
ENTRYPOINT ["executable""param1""param2"]
ENTRYPOINT command param1 param2
 
该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。
当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖,只有最后一个CMD或者ENTRYPOINT有效。
 
# CMD指令将不会被执行,只有ENTRYPOINT指令被执行 
CMD echo “Hello, World!” 
ENTRYPOINT ls -l 
 
另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分;
ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数。
 
FROM ubuntu 
CMD ["-l"
ENTRYPOINT ["/usr/bin/ls"
 
6)USER(设置container容器的用户)
设置指令,设置启动容器的用户,默认是root用户。
 
# 指定memcached的运行用户 
ENTRYPOINT ["memcached"
USER daemon 
或者
ENTRYPOINT ["memcached""-u""daemon"
 
7)EXPOSE(指定容器需要映射到宿主机器的端口)
设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。
要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。
也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项。
 
格式:
EXPOSE <port> [<port>...] 
 
# 映射一个端口 
EXPOSE port1 
# 相应的运行容器使用的命令 
docker run -p port1 image 
   
# 映射多个端口 
EXPOSE port1 port2 port3 
# 相应的运行容器使用的命令 
docker run -p port1 -p port2 -p port3 image 
# 还可以指定需要映射到宿主机器上的某个端口号 
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
 
端口映射是docker比较重要的一个功能,原因在于我们每次运行容器的时候容器的IP地址不能指定而是在桥接网卡的地址范围内随机生成的。
宿主机器的IP地址是固定的,我们可以将容器的端口的映射到宿主机器上的一个端口,免去每次访问容器中的某个服务时都要查看容器的IP的地址。
对于一个运行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID来查看该端口号在宿主机器上的映射端口。
 
8)ENV(用于设置环境变量)
主要用于设置容器运行时的环境变量
 
格式:
ENV <key> <value> 
 
设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环境变量,也可以通过在docker run --env key=value时设置或修改环境变量。
 
假如你安装了JAVA程序,需要设置JAVA_HOME,那么可以在Dockerfile中这样写:
ENV JAVA_HOME /path/to/java/dirent
 
9)ADD(从src复制文件到container的dest路径)
主要用于将宿主机中的文件添加到镜像中
构建指令,所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0;如果是一个目录,那么会将该目录下的所有文件添加到container中,不包括目录;
如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>;
如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。
 
格式:
ADD <src> <dest> 
 
<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url;
<dest> 是container中的绝对路径
 
10)VOLUME(指定挂载点))
设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,
这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。
 
格式:
VOLUME ["<mountpoint>"]
 
例如:
FROM base 
VOLUME ["/tmp/data"]
 
运行通过该Dockerfile生成image的容器,/tmp/data目录中的数据在容器关闭后,里面的数据还存在。
例如另一个容器也有持久化数据的需求,且想使用上面容器共享的/tmp/data目录,那么可以运行下面的命令启动一个容器:
docker run -t -i -rm -volumes-from container1 image2 bash
 
其中:container1为第一个容器的ID,image2为第二个容器运行image的名字。
 
11)WORKDIR(切换目录)
设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效。
 
格式:
WORKDIR /path/to/workdir 
 
# 在/p1/p2下执行vim a.txt 
WORKDIR /p1 WORKDIR p2 RUN vim a.txt 
 
12)ONBUILD(在子镜像中执行)
 
格式:
ONBUILD <Dockerfile关键字> 
 
ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行。

二、Dockerfile使用实例

1)利用dockerfile部署jdk1.7+tomcat7服务环境

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
1)查看docker宿主机镜像
[root@localhost ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
docker.io/ubuntu               latest              0ef2e08ed3fa        6 weeks ago         130 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
docker.io/registry             2.2                 ad379b517aa6        14 months ago       224.5 MB
 
2)编写Dockerfile(注意里面的ubuntu的源要换成国内的,这里我换成了国内阿里的ubuntu源)
[root@localhost ~]# vim Dockerfile
# Pull base image 
FROM docker.io/ubuntu:latest
   
MAINTAINER wangshibo "wang_shibo1987@sina.com" 
   
# update source 
RUN echo "deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse"/etc/apt/sources.list 
RUN apt-get update 
   
# Install curl 
RUN apt-get -y install curl 
   
# Install JDK 7 
RUN cd /tmp &&  curl -L 'http://download.oracle.com/otn-pub/java/jdk/7u65-b17/jdk-7u65-linux-x64.tar.gz' -H 'Cookie: oraclelicense=accept-securebackup-cookie; gpw_e24=Dockerfile' tar -xz 
RUN mkdir -p /usr/lib/jvm 
RUN mv /tmp/jdk1.7.0_65/ /usr/lib/jvm/java-7-oracle/ 
   
# Set Oracle JDK 7 as default Java 
RUN update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-7-oracle/bin/java 300    
RUN update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java-7-oracle/bin/javac 300    
   
ENV JAVA_HOME /usr/lib/jvm/java-7-oracle/ 
   
# Install tomcat7 
RUN cd /tmp && curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' tar -xz 
RUN mv /tmp/apache-tomcat-7.0.8/ /opt/tomcat7/ 
   
ENV CATALINA_HOME /opt/tomcat7 
ENV PATH $PATH:$CATALINA_HOME/bin 
   
ADD tomcat7.sh /etc/init.d/tomcat7 
RUN chmod 755 /etc/init.d/tomcat7 
   
# Expose ports. 
EXPOSE 8080 
   
# Define default command. 
ENTRYPOINT service tomcat7 start && tail -f /opt/tomcat7/logs/catalina.out
 
 
3)编写tomcat7.sh
[root@localhost ~]# vim tomcat7.sh
export JAVA_HOME=/usr/lib/jvm/java-7-oracle/ 
export TOMCAT_HOME=/opt/tomcat7 
   
case $1 in 
start) 
  sh $TOMCAT_HOME/bin/startup.sh 
;; 
stop) 
  sh $TOMCAT_HOME/bin/shutdown.sh 
;; 
restart) 
  sh $TOMCAT_HOME/bin/shutdown.sh 
  sh $TOMCAT_HOME/bin/startup.sh 
;; 
esac 
exit 0
 
4)构建镜像
DOckerfile脚本写好了,需要转换成镜像:
[root@localhost ~]# docker build -t wangshibo/jdk-tomcat --rm=true .
........
Removing intermediate container 09cfba8ebc6b
Successfully built 76b10dd9923f  
 
------------------------------------------------------------------------------------
其中:
-t    表示选择指定生成镜像的用户名,仓库名和tag
--rm=true    表示指定在生成镜像过程中删除中间产生的临时容器。
注意:上面构建命令中最后的.符号不要漏了,表示使用当前目录下的Dockerfile构建镜像
------------------------------------------------------------------------------------
 
以上构建命令执行后,可以查看下镜像是否构建成功
[root@localhost ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
wangshibo/jdk-tomcat           latest              76b10dd9923f        21 minutes ago      771.5 MB
docker.io/ubuntu               latest              0ef2e08ed3fa        6 weeks ago         130 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
docker.io/registry             2.2                 ad379b517aa6        14 months ago       224.5 MB
 
最后利用这个镜像启动容器
[root@localhost ~]# docker run -ti -d --name wangshibo-tomcat -p 8899:8080 wangshibo/jdk-tomcat /bin/bash
c0812ad20bed2f27787565d273f7b02d860de5afab88e853e591dde7d3b0dfc9
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
c0812ad20bed        wangshibo/jdk-tomcat        "/bin/sh -c 'service "   7 seconds ago       Up 6 seconds        0.0.0.0:8899->8080/tcp   wangshibo-tomcat
 
进入容器,查看tomcat进程起来了没
[root@localhost ~]# docker exec -ti wangshibo-tomcat /bin/bash
root@c0812ad20bed:/# ps -ef|grep tomcat
root         1     0  0 06:49 ?        00:00:00 /bin/sh -c service tomcat7 start && tail -f /opt/tomcat7/logs/catalina.out /bin/bash
root        23     1 11 06:49 ?        00:00:04 /usr/lib/jvm/java-7-oracle//bin/java -Djava.util.logging.config.file=/opt/tomcat7/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/opt/tomcat7/endorsed -classpath /opt/tomcat7/bin/bootstrap.jar:/opt/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat7 -Dcatalina.home=/opt/tomcat7 -Djava.io.tmpdir=/opt/tomcat7/temp org.apache.catalina.startup.Bootstrap start
root        24     1  0 06:49 ?        00:00:00 tail -f /opt/tomcat7/logs/catalina.out
root        69    53  0 06:49 ?        00:00:00 grep --color=auto tomcat

最后访问http://本机ip:8899就能打开容器的tomcat页面了

Docker容器创建好之后,尽量不要直接登陆容器内去修改。所以最好容器创建的时候进行目录映射。这样就可以通过映射到宿主机上的文件或目录去共享到容器内。
则上面的wangshibo-tomcat容器可以如下调整操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
c0812ad20bed        wangshibo/jdk-tomcat        "/bin/sh -c 'service "   7 seconds ago       Up 6 seconds        0.0.0.0:8899->8080/tcp   wangshibo-tomcat
 
[root@localhost ~]# docker cp wangshibo-tomcat:/opt/tomcat7/webapps /opt/
 
[root@localhost ~]# docker run -ti -d --name wangshibo-tomcat -v /opt/webapps:/opt/tomcat7/webapps -p 8899:8080 wangshibo/jdk-tomcat /bin/bash
1373d1496c2a6226fe5bb6b4877e854bde68ec3653c04966a1b5d22b98486f7d
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
1373d1496c2a        wangshibo/jdk-tomcat        "/bin/sh -c 'service "   4 seconds ago       Up 2 seconds        0.0.0.0:8899->8080/tcp   wangshibo-tomcat
 
这样让需要修改wangshibo-tomcat容器的代码或上线代码时,只需要操作宿主机的/opt/webapps目录即可。

------------------删除docker images中为none的镜像----------------

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
经常使用Dockerfile制作镜像,Docker build 命令执行后,由于版本更新需要重新创建,那么以前那个版本的镜像就会成为临时镜像,这就是none标签的镜像。,如下:
[root@localhost ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
wangshibo/jdk-tomcat           latest              76b10dd9923f        About an hour ago   771.5 MB
<none>                         <none>              571685f2919c        2 hours ago         130 MB
<none>                         <none>              affbf24261bd        2 hours ago         130 MB
<none>                         <none>              8eee83c3b41d        10 days ago         8.096 MB
<none>                         <none>              b94d96e14644        10 days ago         8.096 MB
docker.io/ubuntu               latest              0ef2e08ed3fa        6 weeks ago         130 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
docker.io/registry             2.2                 ad379b517aa6        14 months ago       224.5 MB
 
对于这些none标签的images,可以通过下面的脚本进行删除(如果无法删除none的images,一般重启docker服务后即可解决):
[root@localhost ~]# vim none_images_rm.sh
#!/bin/bash
docker ps -a | grep "Exited" awk '{print $1 }'|xargs docker stop
docker ps -a | grep "Exited" awk '{print $1 }'|xargs docker rm
docker images|grep none|awk '{print $3 }'|xargs docker rmi
 
[root@localhost ~]# chmod 755 none_images_rm.sh
[root@localhost ~]# sh none_images_rm.sh
 
[root@localhost ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
wangshibo/jdk-tomcat           latest              76b10dd9923f        About an hour ago   771.5 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
docker.io/registry             2.2                 ad379b517aa6        14 months ago       224.5 MB

2)再看一例tomcat容器镜像的Dockerfile制作过程(centos为base镜像)

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
[root@localhost ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
 
提前下载好tomcat和java安装包,放在Docker宿主机的/usr/local/src目录下:
[root@localhost src]# ls
apache-tomcat-7.0.67.tar.gz  jdk-7u79-linux-x64.tar.gz
 
/usr/local/src当前目录下编辑Dockerfile。如下:
即将宿主机本地的tomcat和java安装包拷贝到容器内,并自动解压。
[root@localhost src]# vim Dockerfile
#pull down centos image
FROM docker.io/centos
MAINTAINER wangshibo wang_shibo1987@163.com
#copy jdk and tomcat into image
ADD ./apache-tomcat-7.0.67.tar.gz /usr/local
ADD ./jdk-7u79-linux-x64.tar.gz /usr/local
#set environment variable
ENV JAVA_HOME /usr/local/jdk1.7.0_79
ENV PATH $JAVA_HOME/bin:$PATH
#define entry point which will be run first when the container starts up
ENTRYPOINT /usr/local/apache-tomcat-7.0.67/bin/startup.sh && tail -F /usr/local/apache-tomcat-7.0.67/logs/catalina.out
 
 
接着构建镜像
[root@localhost src]# docker build -t kevin_tomcat7 --rm=true .
 
[root@localhost src]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
kevin_tomcat7                  latest              8f242680d940        11 seconds ago      511.6 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
 
根据制作的镜像启动tomcat容器
[root@localhost src]# docker run -ti -d --name tomcat-test -p 8899:8080 kevin_tomcat7 /bin/bash
22dece8d6660b61677bf89137d5d21548c2f0b0fd337ce5a1e12ef6d2000091a
 
[root@localhost src]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
22dece8d6660        kevin_tomcat7               "/bin/sh -c '/usr/loc"   4 seconds ago       Up 4 seconds        0.0.0.0:8899->8080/tcp   tomcat-test
 
[root@localhost src]# docker exec -ti tomcat-test /bin/bash
[root@22dece8d6660 /]# ps -ef|grep tomcat
root         1     0  0 08:59 ?        00:00:00 /bin/sh -c /usr/local/apache-tomcat-7.0.67/bin/startup.sh && tail -F /usr/local/apache-tomcat-7.0.67/logs/catalina.out /bin/bash
root        20     1  9 08:59 ?        00:00:05 /usr/local/jdk1.7.0_79/bin/java -Djava.util.logging.config.file=/usr/local/apache-tomcat-7.0.67/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/apache-tomcat-7.0.67/endorsed -classpath /usr/local/apache-tomcat-7.0.67/bin/bootstrap.jar:/usr/local/apache-tomcat-7.0.67/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/apache-tomcat-7.0.67 -Dcatalina.home=/usr/local/apache-tomcat-7.0.67 -Djava.io.tmpdir=/usr/local/apache-tomcat-7.0.67/temp org.apache.catalina.startup.Bootstrap start
root        21     1  0 08:59 ?        00:00:00 tail -F /usr/local/apache-tomcat-7.0.67/logs/catalina.out
root        67    47  0 09:00 ?        00:00:00 grep --color=auto tomcat

3)使用Dockerfile制作nginx镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost mnt]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
 
制作Dockerfile
[root@localhost mnt]# vim Dockerfile
#pull down centos image
FROM docker.io/centos
MAINTAINER wangshibo wang_shibo1987@163.com
 
#install nginx
RUN yum install -y pcre pcre-devel openssl openssl-devel gcc gcc+ wget vim net-tools
RUN useradd www -M -s /sbin/nologin
RUN cd /usr/local/src && wget http://nginx.org/download/nginx-1.8.0.tar.gz && tar -zxvf nginx-1.8.0.tar.gz
RUN cd /usr/local/src/nginx-1.8.0 && ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module && make && make install
 
ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log

---------------------------------------------------------------------------------------------------------------------
特别需要注意的:
在Docker daemon模式下,无论你是使用ENTRYPOINT,还是CMD,最后的命令,一定要是当前进程需要一直运行的,才能够防容器退出。
也就是说,上面Dockerfile脚本中最后一行:

以下无效方式:
ENTRYPOINT /usr/local/nginx/sbin/nginx             #运行几秒钟之后,容器就会退出
或者
CMD /usr/local/nginx/sbin/nginx             #运行几秒钟之后,容器就会退出

以下才是有效方式:
ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log     #确保容器内的进程一直运行
或者
CMD /usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log       #确保容器内的进程一直运行

其他应用程序镜像创建的Dockerfile配置类似
------------------------------------------------------------------------------------------------------------------

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
构建镜像
[root@localhost mnt]# docker build -t kevin_nginx --rm=true .
 
[root@localhost mnt]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
kevin_nginx                    latest              e4967a39dd54        23 seconds ago      411.1 MB
docker.io/centos               latest              67591570dd29        3 months ago        191.8 MB
 
根据Dockerfile构建的镜像启动nginx容器
[root@localhost mnt]# docker run -ti -d --name test_nginx -p 8899:80 kevin_nginx /bin/bash
8725aceba170722cd57a4f20fd843634ee5c5d75f1c2726c1e98f66b8102a179
 
[root@localhost mnt]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
8725aceba170        kevin_nginx                 "/bin/sh -c '/usr/loc"   2 seconds ago       Up 1 seconds        0.0.0.0:8899->80/tcp     test_nginx
 
进入容器,检查容器内的nginx程序是否已启动
[root@localhost mnt]# docker exec -ti test_nginx /bin/bash
[root@8725aceba170 /]# ps -ef|grep nginx
root         1     0  0 11:15 ?        00:00:00 /bin/sh -c /usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log /bin/bash
root        13     1  0 11:15 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
www         14    13  0 11:15 ?        00:00:00 nginx: worker process
root        15     1  0 11:15 ?        00:00:00 tail -f /usr/local/nginx/logs/access.log
root        38    16  0 11:16 ?        00:00:00 grep --color=auto nginx

通过映射到Docker宿主机的端口8080去访问容器的nginx

依据上面制定的kevin_nginx镜像在创建容器时,还可以使用-v参数映射宿主机目录或文件到容器里。做法如下:

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
1)先如上创建test_nginx容器
 [root@localhost mnt]# docker run -ti -d --name test_nginx -p 8899:80 kevin_nginx /bin/bash
8725aceba170722cd57a4f20fd843634ee5c5d75f1c2726c1e98f66b8102a179
  
[root@localhost mnt]# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
8725aceba170        kevin_nginx                 "/bin/sh -c '/usr/loc"   2 seconds ago       Up 1 seconds        0.0.0.0:8899->80/tcp     test_nginx
  
2)在宿主机上创建映射目录
[root@localhost mnt]# mkdir -p /data/container/nginx
[root@localhost mnt]# cd /data/container/nginx
[root@localhost nginx]# mkdir conf html
  
然后将上面test_nginx容器中的/usr/loca/nginx/conf 配置目录和/usr/local/nginx/html数据目录拷贝到宿主机上
[root@localhost nginx]# pwd
/data/container/nginx
[root@localhost nginx]# docker cp 8725aceba170:/usr/local/nginx/conf ./
[root@localhost nginx]# docker cp 8725aceba170:/usr/local/nginx/html ./
[root@localhost nginx]# ls conf/
fastcgi.conf          fastcgi_params.default  mime.types          nginx.conf.default   uwsgi_params
fastcgi.conf.default  koi-utf                 mime.types.default  scgi_params          uwsgi_params.default
fastcgi_params        koi-win                 nginx.conf          scgi_params.default  win-utf
[root@localhost nginx]# ls html/
50x.html  index.html
  
然后删除test_nginx容器
[root@localhost nginx]# docker stop test_nginx
[root@localhost nginx]# docker rm test_nginx
  
重新创建新容器
[root@localhost nginx]# docker run -d --name bobo_nginx -v /data/contain/nginx/conf/:/usr/local/nginx/conf/ -v /data/contain/nginx/html/:/usr/local/nginx/html/ -p 80:80 kevin_nginx
a5f7fb2c32dcef78dad79caf1cdb11323fb498542c50782040ca24b0a52d624e
  
[root@localhost nginx]# docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                           NAMES
a5f7fb2c32dc        kevin_nginx   "/bin/sh -c '/usr/..."   2 seconds ago       Up 1 second         443/tcp, 0.0.0.0:80->80/tcp   bobo_nginx
  
然后就可以直接编辑宿主机的 /data/contain/nginx/conf里面的nginx.conf配置以及 /data/contain/nginx/html来控制容器的nginx服务了。
[root@localhost nginx]# cat conf/nginx.conf
user  www;
worker_processes  8;
   
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
   
#pid        logs/nginx.pid;
   
   
events {
    worker_connections  65535;
}
   
   
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
         
    ######
    ## set access log format
    ######
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
   
    #######
    ## http setting
    #######
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
    #proxy_cache_path /var/www/cache levels=1:2 keys_zone=mycache:20m max_size=2048m inactive=60m;
    #proxy_temp_path /var/www/cache/tmp;
   
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
   
    #
    client_header_timeout 600s;
    client_body_timeout 600s;
   # client_max_body_size 50m;
    client_max_body_size 100m;           
    client_body_buffer_size 256k;          
   
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
   
    ## includes vhosts
    include vhosts/*.conf;
}
  
[root@localhost nginx]# cat conf/vhosts/test.conf
server {
     listen       80;
     server_name  localhost;
    
      access_log  /usr/local/nginx/logs/test-access.log main;
      error_log  /usr/local/nginx/logs/test-error.log;
  
      root   /usr/local/nginx/html;
  }
  
编辑好配置之后,记得要重启容器,使得配置生效!
[root@localhost nginx]# docker restart bobo_nginx
  
=============================================
温馨提示:
通过上面的操作后,如果删除bobo_nginx容器,然后再次创建容器,就会发现容器创建之后是起不来的!
[root@localhost nginx]# docker stop bobo_nginx
bobo_nginx
[root@localhost nginx]# docker rm bobo_nginx
bobo_nginx
[root@localhost nginx]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  
[root@localhost nginx]# docker run -d --name bobo_nginx -v /data/contain/nginx/conf/:/usr/local/nginx/conf/ -v /data/contain/nginx/html/:/usr/local/nginx/html/ -p 80:80 kevin_nginx
ea677eeb38794e0d3b09a508c8df504aa08ef27385fa35647414582be33b293d
  
[root@localhost nginx]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  
[root@localhost nginx]# docker ps -a
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS                     PORTS               NAMES
ea677eeb3879        kevin_nginx   "/bin/sh -c '/usr/..."   4 seconds ago       Exited (1) 3 seconds ago                       bobo_nginx
  
这个时候使用docker logs查看容器启动失败的日志
[root@localhost nginx]# docker logs bobo_nginx
tail: cannot open '/usr/local/nginx/logs/access.log' for reading: No such file or directory
tail: no files remaining
  
这是因为宿主机的/data/contain/nginx/conf/vhosts/test.conf里面定义的access日志是test-access.log,而nginx启动默认的日志是access.log。
由于使用了-v映射宿主机目录到容器了,所以出现了上面报错!
  
解决办法:
1)第一种方法
/data/contain/nginx/conf/vhosts/test.conf修改如下:
[root@localhost nginx]# cat conf/vhosts/test.conf
server {
     listen       80;
     server_name  localhost;
    
      access_log  /usr/local/nginx/logs/access.log main;
      error_log  /usr/local/nginx/logs/error.log;
  
      root   /usr/local/nginx/html;
  }
 
2)第二种方法(推荐这一种)
就是在宿主机映射目录下再加一个logs,创建容器时添加上这个logs的映射关系,这样也便于后续处理应用容器的log问题。
创建容器前提前把自定义的log文件手动创建好。
[root@localhost nginx]# mkdir /data/contain/nginx/logs
[root@localhost nginx]# cd /data/contain/nginx/logs
[root@localhost logs]# touch test-access.log
[root@localhost logs]# touch test-error.log
  
然后接着再次重新创建就成功了!
[root@localhost nginx]# docker rm bobo_nginx
[root@localhost nginx]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  
[root@localhost nginx]# docker run -d --name bobo_nginx -v /data/contain/nginx/conf/:/usr/local/nginx/conf/ -v /data/contain/nginx/html/:/usr/local/nginx/html/ -v /data/contain/nginx/logs/:/usr/local/nginx/logs/ -p 80:80 kevin_nginx
27480950d33e0c445574d8393541751f2a51e8f65484322d3ee0b4c6b0569d2f
  
[root@localhost nginx]# docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                           NAMES
27480950d33e        kevin_nginx   "/bin/sh -c '/usr/..."   3 seconds ago       Up 2 seconds        443/tcp, 0.0.0.0:80->80/tcp   bobo_nginx
  
需要注意的是:
1)一旦使用-v参数创建容器时添加映射关系后,就一定要小心宿主机映射目录下的操作,因为此时两边时实时同步的,别一不小心就删除或修改了数据。
2)修改映射文件后,涉及到服务配置文件的,要记得使用docker restart重启容器,使之生效!
3)一旦容器创建后,启动报错,要记得使用docker logs 查看容器日志
4)在做映射关系前,要先创建一个初始容器,将容器里要映射的文件或目录先docker cp拷贝到宿主机的对应目录下,接着删除初始容器,然后再使用
  -v参数进行带有映射目录关系的容器创建。创建后,就可以操作宿主机映射后的文件了。

创建好的镜像,可以保存到索引仓库中,便于下次使用(当然,我们直接共享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
登陆https://hub.docker.com/  注册一个账号
  
然后登陆
[root@localhost mnt]# docker login
Username: wangshibo
Password:
Email: wang_shibo1987@163.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
  
提交到Docker索引仓库
注意下面提交的镜像路径,即"用户名/镜像",只有这样才能成功提交。
所以在Dockerfile制作镜像的时候,仓库名最好用docker索引仓库的用户名,也即"用户名/镜像"
[root@localhost mnt]# docker push wangshibo/jdk-tomcat
The push refers to a repository [docker.io/wangshibo/jdk-tomcat]
8363b5ccd5b3: Pushed
a619e846ce29: Pushed
578822b85971: Pushing [================================>                  ] 6.859 MB/10.57 MB
b979d350733e: Pushed
a6b994571424: Pushed
eb80782ddf9c: Pushed
.......
  
这样下次想用的时候,可以直接从Docker索引仓库里下载
docker pull wangshibo/jdk-tomcat 

原文出处:https://www.cnblogs.com/kevingrace/p/6698596.html

Docker容器日常操作命令的更多相关文章

  1. Docker容器的操作命令

    Docker容器的操作命令 写该文章时候的初衷是在使用Docker for windows 的时候遇到的一些问题.起初我在运行好docker客户端以后,创建了一个.NET Core应用发布到docke ...

  2. docker容器使用

    查看容器的配置信息 # docker inspect dc4e2ff3eb58 查看容器的网络信息 # docker inspect -f {{.NetworkSettings}} node4 [ro ...

  3. Docker 容器操作命令

    容器是镜像的一个运行实例,镜像是静态的只读文件,而容器带有运行时需要的可写文件层.如果认为虚拟机是模拟运行的一整套操作系统(包括内核.应用运行态环境和其他系统环境)和跑在上面的应用,那么Docker容 ...

  4. Docker容器学习梳理 - 日常操作总结

    使用Docker已有一段时间了,今天正好有空梳理下自己平时操作Docker时的一些命令和注意细节: Docker 命令帮助 $ sudo docker Commands: attach Attach ...

  5. docker容器登录,退出等操作命令

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口 ...

  6. [CoreOS 转载] CoreOS实践指南(七):Docker容器管理服务

    转载:http://www.csdn.net/article/2015-02-11/2823925 摘要:当Docker还名不见经传的时候,CoreOS创始人Alex就预见了这个项目的价值,并将其做为 ...

  7. 快速理解Docker - 容器级虚拟化解决方案

    是什么 简单的说Docker是一个构建在LXC之上的,基于进程容器(Processcontainer)的轻量级VM解决方案 拿现实世界中货物的运输作类比, 为了解决各种型号规格尺寸的货物在各种运输工具 ...

  8. [转]20个令人惊叹的桌面Docker容器

    大家好,今天我们会列出一些运行在Docker容器中的很棒的桌面软件,我们可以在自己的桌面系统中运行它们.Docker 是一个开源项目,提供了一个可以打包.装载和运行任何应用的轻量级容器的开放平台.它没 ...

  9. 使用 Dashboard - 每天5分钟玩转 Docker 容器技术(174)

    上一节我们完成了 Kubernetes Dashboard 的安装,本节就来实践一下. Dashboard 界面结构 Dashboard 的界面很简洁,分为三个大的区域. 顶部操作区在这里用户可以搜索 ...

随机推荐

  1. Oracle创建表 创建库 数据恢复

    --建用户CREATE USER szs IDENTIFIED BY szs DEFAULT TABLESPACE NN_DATA01 TEMPORARY TABLESPACE temp;--用户赋权 ...

  2. ES6新数据类型Symbol

    Symbol 需计算字面量属性时使用 const benz = Symbol('benz'); const car = { [benz]: 'benz car' }; const info = Sym ...

  3. Django forms组件的校验

    引入: from django import forms 使用方法:定义规则,例: class UserForm(forms.Form): name=forms.CharField(max_lengt ...

  4. HTTP协议详解??

    HTTP协议: HTTP (hypertext transport protocol) , 即 超 文 本 传 输 协 议 . 这 个 协 议 详 细 规 定 了 浏 览 器 和 万 维 网 服 务 ...

  5. Elasticsearch学习,请先看这一篇!

    原文:Elasticsearch学习,请先看这一篇! 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...

  6. JS中类或对象的定义说明

    本篇文章主要是对JS中类或对象的定义进行说明介绍.我们知道,JS是面向对象的.谈到面向对象,就不可避免的要涉及类的概念.一般像c#,java这些强类型语言都有固定的定义类的语法.而JS的不同之处在于它 ...

  7. 3-基于双TMS320C6678+双XC6VSX315T的6U VPX高速数据处理平台

    基于双TMS320C6678+双XC6VSX315T的6U VPX高速数据处理平台   一.板卡概述 板卡由我公司自主研发,基于VPX架构,主体芯片为两片 TI DSP TMS320C6678,两片V ...

  8. [SDOI2015]寻宝游戏(LCA,set)

    [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到 ...

  9. 补比赛——牛客OI周赛9-普及组

    比赛地址 A 小Q想撸串 题目分析 普及T1水题惯例.字符串中找子串. Code #include<algorithm> #include<iostream> #include ...

  10. CSS3 Transform实例

    移动translate <!doctype html> <html> <head> <meta charset="utf-8"> & ...