Fork me on GitHub

Docker梦工厂

Docker

小述Docker

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

Centos7下部署Docker

docker安装

  1. 首先检查内核版本,要求必须要在3.10+

    1
    uname -r
  2. 确保yum是最新的(可以忽略此步)

    1
    yum update
  3. 添加docker于yum仓库

    1
    2
    3
    4
    5
    6
    7
    8
    tee /etc/yum.repos.d/docker.repo <<-'EOF'
    [dockerrepo]
    name=Docker Repository
    baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
    enabled=1
    gpgcheck=1
    gpgkey=https://yum.dockerproject.org/gpg
    EOF
  4. 安装docker

    1
    yum install -y docker-engine

启动验证

启动/重启/停止的命令

1
2
3
systemctl start docker
systemctl restart docker
systemctl stop docker

验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker version

Client:
Version: 17.05.0-ce
API version: 1.29
Go version: go1.7.5
Git commit: 89658be
Built: Thu May 4 22:06:25 2017
OS/Arch: linux/amd64
Server:
Version: 17.05.0-ce
API version: 1.29 (minimum version 1.12)
Go version: go1.7.5
Git commit: 89658be
Built: Thu May 4 22:06:25 2017
OS/Arch: linux/amd64
Experimental: false

镜像管理

启动docker后可以查看此时拥有的镜像源:

1
docker image

  1. 下载拉取镜像源

    1
    2
    //例:拉取tomcat镜像
    docker pull hub.c.163.com/library/tomcat:latest
  2. 修改镜像名和标签

    1
    docker tag hub.c.163.com/library/tomcat:latest tomcat:v8.5
  3. 删除原来的镜像

    1
    docker rmi -f hub.c.163.com/library/tomcat:latest
  4. 将该服务在后台运行起来(并指定由服务器58080端口对其映射)

    1
    docker run -d -p 58080:8080 tomcat:v8.5
  5. 查看

    1
    2
    //查看运行中的容器信息
    docker ps

此时在浏览器即可访问此时运行的tomcat了,并且是在我们指定的58080端口:

1
http://ip:58080

与docker的亲密接触

日常命令

  1. 登录(登出)一个Docker镜像仓库,如未指定仓库地址,默认为官方仓库Docker Hub

    1
    2
    3
    4
    docker login [option] [server]
    docker logout [option] [server]
    //例:
    docker login -u 用户名 -p 密码
  2. 从Docker Hub中查找镜像

    1
    2
    3
    4
    docker search [option] team
    --automated :只列出 automated build类型的镜像;
    --no-trunc :显示完整的镜像描述;
    -s :列出收藏数不小于指定值的镜像。
  3. 将本地镜像上传到镜像仓库(必须先登录)

    1
    2
    docker push [options] name[:tag]
    --disable-content-trust 忽略镜像的校验,默认开启
  4. 从镜像仓库中拉取或更新指定仓库

    1
    docker pull [options] name[:tag|@digest]
  5. 列出本地镜像

    1
    docker images [options] [repository[:tag]]
  6. 删除一个或多个本地镜像

    1
    2
    3
    docker rmi [options] image [image ...]
    -f 强制删除
    --no-prune 不移除该镜像的过程镜像,默认移除
  7. 标记本地镜像,将其归入某一仓库(修改镜像名)

    1
    docker tag [options] image[:tag] name[:tag]
  8. 使用Dockerfile创建镜像

    1
    2
    3
    4
    5
    6
    7
    docker build [options] path | url | -
    -f 指定要使用的Dockerfile的路径
    -m 设置内存最大值
    -q 安静模式,成功后只输出镜像ID
    --rm 设置镜像成功后删除中间容器
    //例:
    docker build -t /fy/tomcat:v8.5 .
  9. 查看指定镜像的创建历史

    1
    docker history [options] image
  10. 将指定镜像保存成tar归档文件

    1
    2
    docker save [options] image [image ...]
    -o 输出到的文件
  11. 从归档文件中创建镜像

    1
    2
    3
    4
    5
    docker import [options] file|url|- [repository[:tag]]
    -c 应用docker指令创建镜像
    -m 提交时的说明文字
    //例:
    docker import abc.tar fy/tomcat:v8.5
  12. 创建一个新的容器但不启动

    1
    docker create [options] image [command] [arg ...]
  13. 创建一个新的容器并运行一个命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    docker run [options] image [command] [arg ...]
    -d: 后台运行容器,并返回容器ID;
    -i: 以交互模式运行容器,通常与 -t 同时使用;
    -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
    --name="nginx-lb": 为容器指定一个名称;
    --dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
    --dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
    -h "mars": 指定容器的hostname;
    -e username="ritchie": 设置环境变量;
    --env-file=[]: 从指定文件读入环境变量;
    --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
    -m :设置容器使用内存最大值;
    --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
    --link=[]: 添加链接到另一个容器;
    --expose=[]: 开放一个端口或一组端口
    -p:指定映射端口 服务器端口:容器端口
    -P:系统自动为其分配映射端口
  14. 杀掉一个运行中的容器

    1
    2
    docker kill [options] container [container ...]
    -s 向容器发送一个信号
  15. 删除一个或多少容器

    1
    2
    3
    4
    docker rm [options] container [container ...]
    -f 通过SIGKILL信号强制删除一个运行中的容器
    -l 移除容器间的网络连接,而非容器本身(后接连接名,不是容器名)
    -v 删除容器和与容器相关联的卷
  16. 暂停/恢复容器中的所有进程

    1
    2
    docker pause [options] container [container ...]
    docker unpause [options] container [container ...]
  17. 在运行的容器中执行命令

    1
    2
    3
    4
    5
    6
    7
    8
    docker exec [options] container command [arg ...]
    -d :分离模式: 在后台运行
    -i :即使没有附加也保持STDIN 打开
    -t :分配一个伪终端
    //例:在容器test中以交互模式执行容器内的/root/run.sh脚本
    docker exec -ti test /bin/sh /root/run.sh
    //例:在容器test中开启一个交互模式的终端(即进入test容器)
    docker exec -ti test /bin/bash
  18. 列出容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker ps [options]
    -a :显示所有的容器,包括未运行的。
    -f :根据条件过滤显示的内容。
    --format :指定返回值的模板文件。
    -l :显示最近创建的容器。
    -n :列出最近创建的n个容器。
    --no-trunc :不截断输出。
    -q :静默模式,只显示容器编号。
    -s :显示总的文件大小。
  19. 获取容器/镜像的元数据

    1
    2
    3
    4
    docker inspect [options] name|id [name|id ...]
    -f :指定返回值的模板文件。
    -s :显示总的文件大小。
    --type :为指定类型返回JSON。
  20. 查看容器中运行的进程信息,支持ps命令参数

    1
    docker top [options] container [ps options]
  21. 从服务器获取实时事件

    1
    2
    3
    4
    docker events [options]
    -f :根据条件过滤事件;
    --since :从指定的时间戳后显示所有事件;
    --until :流水时间显示到指定的时间为止;
  22. 获取容器的日志

    1
    2
    3
    4
    5
    docker logs [options] container
    -f : 跟踪日志输出
    --since :显示某个开始时间的所有日志
    -t : 显示时间戳
    --tail :仅列出最新N条容器日志
  23. 阻塞运行直到停止,最后打印它的退出代码

    1
    docker wait [options] container [container ...]
  24. 从容器创建一个新的镜像

    1
    2
    3
    4
    5
    docker commit [options] container [repository[:tag]]
    -a :提交的镜像作者;
    -c :使用Dockerfile指令来创建镜像;
    -m :提交时的说明文字;
    -p :在commit时,将容器暂停。
  25. 容器与主机之间的数据拷贝

    1
    2
    3
    docker cp [options] container:src_path dest_path
    docker cp [options] src_path container:dest_path
    -L 保持源目标中的链接
  26. 检查容器里文件结构的更改

    1
    docker diff [options] container

额外需求

给普通用户添加使用docker的权限

这样普通就可以使用docker命令而无需root权限。

1
2
3
usermod -a -G docker 用户名
systemctl restart docker
注意:该用户需要重新登录才生效

制作自己的镜像

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
//此例为tomcat7.0
//新建tomcat7.0的母文件夹
mkdir dockerfile_tomcat7.0-2
//将tomcat7.0和jdk1.7移入该文件夹
cp tomcat7.0 dockerfile_tomcat7.0-2/tomcat7.0
cp jdk1.7 dockerfile_tomcat7.0-2/jdk1.7
cd dockerfile_tomcat7.0-2
//创建编辑Dockerfile文件
vim Dockerfile
//以下为Dockerfile文件内容->开始
#使用基础镜像centos:7.2(此镜像已拉取下来)
FROM centos:v7.2
#指定镜像创建者信息
MAINTAINER fy
#切换镜像的目录,进入/usr目录(基础镜像是一个linux系统,可参照linux查看相应目录)
WORKDIR /usr
#在/usr/下创建java目录,用来存放jdk
RUN mkdir java
#切换镜像的目录至/usr/java
WORKDIR /usr/java
#在/usr/java下创建jdk目录,用来存放jdk文件
RUN mkdir jdk
#切换镜像的目录至/usr/java/jdk
WORKDIR /usr/java/jdk
#将宿主机的jdk1.7目录下的全部文件考入至镜像的/usr/java/jdk目录下
ADD jdk1.7 /usr/java/jdk
#切换镜像的目录至/opt
WORKDIR /opt
#在/opt下创建tomcat目录,用来存放tomcat文件
RUN mkdir tomcat
#将宿主机的tomcat7.0目录下的全部文件考入至镜像的/opt/tomcat目录下
ADD tomcat7.0 /opt/tomcat
#设置环境变量
ENV JAVA_HOME=/usr/java/jdk
ENV JAVA_BIN=/usr/java/jdk/bin
ENV PATH=$PATH:$JAVA_HOME/bin
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
#设置容器启动时执行的操作

CMD /opt/tomcat/bin/catalina.sh run
//以上为Dockerfile文件的内容->结束
//产生镜像
docker build -t tomcat:v7.0-2 .
//此时可以查看
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat v7.0-2 5a9f994d6a14 About a minute ago 845MB
//启动该tomcat(如果要看启动错误,就不要加-d后台参数)
docker run -d -p 48080:8080 tomcat:v7.0-2

报错解决:

1
2
3
4
5
6
7
8
报错:在启动tomcat(./startup.sh)如果报
-bash: ./startup.sh: Permission denied
解决:解决(进入tomcat的bin目录赋权限)
chmod u+x *.s
报错:在启动时如果报
The APR based Apache Tomcat Native library which allows optimal
解决:解决(下载tcnative-1.dll,放到tocat的bin目录下)
wget http://tomcat.heanet.ie/native/1.1.12/binaries/win32/tcnative-1.dll

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
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
常用:
FROM:base镜像
RUN:执行命令
ADD:添加文件
COPY:拷贝文件
CMD:执行命令
EXPOSE:暴露端口
WORKDIR:指定路径
MAINTAINER:维护者(作者)
ENV:设定环境变量
ENTRYPORT:容器入口
USER:指定用户
VOLUME:mount point

命令详解:
FROM
功能为指定基础镜像,并且必须是第一条指令。
如果不以任何镜像为基础,那么写法为:FROM scratch。
同时意味着接下来所写的指令将作为镜像的第一层开始
语法:
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
三种写法,其中<tag><digest> 是可选项,如果没有选择,那么默认值为latest
RUN
功能为运行指定的命令
RUN命令有两种格式
1. RUN <command>
2. RUN ["executable", "param1", "param2"]
第一种后边直接跟shell命令

* 在linux操作系统上默认 /bin/sh -c
* 在windows操作系统上默认 cmd /S /C

第二种是类似于函数调用。
可将executable理解成为可执行文件,后面就是两个参数。
两种写法比对:

* RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
* RUN ["/bin/bash", "-c", "echo hello"]

注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.
多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
RUN书写时的换行符是\
CMD
功能为容器启动时要运行的命令
语法有三种写法
1. CMD ["executable","param1","param2"]
2. CMD ["param1","param2"]
3. CMD command param1 param2
第三种比较好理解了,就时shell这种执行方式和写法
第一种和第二种其实都是可执行文件加上参数的形式
举例说明两种写法:

* CMD [ "sh", "-c", "echo $HOME"
* CMD [ "echo", "$HOME" ]

补充细节:这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。
原因是参数传递后,docker解析的是一个JSON array
RUN & CMD
不要把RUN和CMD搞混了。
RUN是构件容器时就运行的命令以及提交运行结果
CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子
LABEL
功能是为镜像指定标签
语法:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
一个Dockerfile中可以有多个LABEL,如下:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号
如下:
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖
MAINTAINER
指定作者
语法:
MAINTAINER <name>
EXPOSE
功能为暴露容器运行时的监听端口给外部
但是EXPOSE并不会使容器访问主机的端口
如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数
ENV
功能为设置环境变量
语法有两种
1. ENV <key> <value>
2. ENV <key>=<value> ...
两者的区别就是第一种是一次设置一个,第二种是一次设置多个
ADD
一个复制命令,把文件复制到镜像中。
如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用。
语法如下:
1. ADD <src>... <dest>
2. ADD ["<src>",... "<dest>"]
<dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
<src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
如果把<src>写成一个url,那么ADD就类似于wget命令
如以下写法都是可以的:

* ADD test relativeDir/
* ADD test /relativeDir
* ADD http://example.com/foobar /

尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据
COPY
又是一个复制命令
语法如下:
1. COPY <src>... <dest>
2. COPY ["<src>",... "<dest>"]
与ADD的区别
COPY的<src>只能是本地文件,其他用法一致
ENTRYPOINT
功能是启动时的默认命令
语法如下:
1. ENTRYPOINT ["executable", "param1", "param2"]
2. ENTRYPOINT command param1 param2
第二种就是写shell
第一种就是可执行文件加参数
与CMD比较说明(这俩命令太像了,而且还可以配合使用):
1. 相同点:

* 只能写一条,如果写了多条,那么只有最后一条生效
* 容器启动时才运行,运行时机相同

2. 不同点:

* ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖
* 如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数

如下:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

* 如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效

如下:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ls -al
那么将执行ls -al ,top -b不会执行。
VOLUME
可实现挂载功能,可以将内地文件夹或者其他容器中的文件夹挂在到这个容器中
语法为:
VOLUME ["/data"]
说明:
["/data"]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
一般的使用场景为需要持久化存储数据时
容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。
所以当数据需要持久化时用这个命令。
USER
设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的

* USER daemo
* USER UID

注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行
WORKDIR
语法:
WORKDIR /path/to/workdir
设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。
如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
pwd执行的结果是/a/b/c
WORKDIR也可以解析环境变量
如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
pwd的执行结果是/path/$DIRNAME
ARG
语法:
ARG <name>[=<default value>]
设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数
如果用户在build镜像时指定了一个参数没有定义在Dockerfile中,那么将有一个Warning
提示如下:
[Warning] One or more build-args [foo] were not consumed.
我们可以定义一个或多个参数,如下:
FROM busybox
ARG user1
ARG buildno
...
也可以给参数一个默认值:
FROM busybox
ARG user1=someuser
ARG buildno=1
...
如果我们给了ARG定义的参数默认值,那么当build镜像时没有指定参数值,将会使用这个默认值
ONBUILD
语法:
ONBUILD [INSTRUCTION]
这个命令只对当前镜像的子镜像生效。
比如当前镜像为A,在Dockerfile种添加:
ONBUILD RUN ls -al
这个 ls -al 命令不会在A镜像构建或启动的时候执行
此时有一个镜像B是基于A镜像构建的,那么这个ls -al 命令会在B镜像构建的时候被执行。
STOPSIGNAL
语法:
STOPSIGNAL signal
STOPSIGNAL命令是的作用是当容器退出时给系统发送什么样的指令
HEALTHCHECK
容器健康状况检查命令
语法有两种:
1. HEALTHCHECK [OPTIONS] CMD command
2. HEALTHCHECK NONE
第一个的功能是在容器内部运行一个命令来检查容器的健康状况
第二个的功能是在基础镜像中取消健康检查命令
[OPTIONS]的选项支持以下三种选项:
--interval=DURATION 两次检查默认的时间间隔为30秒
--timeout=DURATION 健康检查命令运行超时时长,默认30秒
--retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3
注意:
HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:
0: success - 表示容器是健康的
1: unhealthy - 表示容器已经不能工作了
2: reserved - 保留值
例子:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
健康检查命令是:curl -f http://localhost/ || exit 1
两次检查的间隔时间是5秒
命令超时时间为3秒

上面知识点很多,字太多,手敲有点累,博主直接从笔记中copy出来,还望读者见谅!

希望大家在Docker梦工厂中畅游后能有所收获,也不负博主整理编辑了半天,hhh~
-------------本文结束感谢您的阅读-------------
如果您对博主的原创满意,欢迎您继续支持下博主~