Docker安装

Docker安装(CentOS 7)

Docker在CentOS 7上的安装,直接参考官网安装手册即可: Install Docker Engine on CentOS

安装Dockerd主版本的步骤如下,要按照特定版本的,参考Docker官网。

1
2
3
4
5
6
7
sudo yum -y install epel-release
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# sudo yum list docker-ce --showduplicates | sort -r
sudo yum -y install docker-ce docker-ce-cli containerd.io -y
sudo systemctl start docker
systemctl enable docker

执行docker version来验证docker是否正常安装。

Tips:
也可以换用阿里云的docker镜像源yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

设置镜像加速

设置网易云镜像加速

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

检查镜像加速是否设置成功, 查看Registry Mirrors中是否有163的镜像。

1
2
3
4
5
6
7
$ docker info
...
Registry Mirrors:
http://hub-mirror.c.163.com/
...
$

执行hello-world镜像

1
docker run hello-world

Docker命令

Docker帮助命令

1
2
3
docker version
docker info # 输出docker目前的状态概述,包括系统资源,镜像和容器数量等
docker COMMAND --help # 依次逐级获取命令支持的参数和作用

镜像命令

列出本机镜像

列出本地的镜像docker images, 使用REPOSITORY:TAG来定义不同的镜像

1
2
3
4
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 9 months ago 13.3kB
[root@localhost ~]#

参数

  • -a: 列出所有的镜像
  • -q: 列出镜像的ID
  • --digests: 显示镜像的digest摘要信息
  • --no-trunc: 显示ID的完整信息

搜索镜像

docker search从Docker Hub上搜索镜像

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# docker search tomcat
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
tomcat Apache Tomcat is an open source implementati… 2847 [OK]
tomee Apache TomEE is an all-Apache Java EE certif… 83 [OK]
dordoka/tomcat Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 base… 55 [OK]
bitnami/tomcat Bitnami Tomcat Docker Image 36 [OK]
kubeguide/tomcat-app Tomcat image for Chapter 1 29
consol/tomcat-7.0 Tomcat 7.0.57, 8080, "admin/admin" 17 [OK]
...
[root@localhost ~]#

其中OFFICIAL表示是否是官方镜像,STARS表示星星数。

常用参数

  • --filter: 加上过滤条件,比如--filter=stars=10就是索索star数大于等于10的镜像
  • --no-trunc: 输出完整的信息,比如Description中不要省略

拉取镜像

docker pull拉取镜像,docker pull IMAGE_NAME:TAG,如果省略TAG,那么默认拉取latest

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
df20fa9351a1: Pulling fs layer
latest: Pulling from library/alpine
df20fa9351a1: Pull complete
Digest: sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
[root@localhost ~]#

删除镜像

docker rmi用来删除镜像
如果镜像被某个container在使用时,删除会提示类似Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container a8a7d78cf5b4 is using its referenced image bf756fb1ae65的错误信息。
此时加上-f参数进行强制删除即可,docker rmi hello-world -f

1
2
3
4
5
6
7
8
# 删除单个
docker rmi -f 镜像ID:TAG
# 删除多个
docker rmi -f 镜像ID_1:TAG 镜像ID_2:TAG
# 删除全部
docker rmi -f $(docker images -qa)

容器命令

新建并启动容器

docker run: 按照某个镜像新建容器示例。

1
docker run -it 7e6257c9f8d8

常用参数:

  • --name: 执行容器名字
  • -d: 后台运行容器
  • -i: 以命令交互模式运行容器,常和-t同时使用
  • -t: 为容器重新分配一个伪输入终端,通常和-i一起使用
  • -P: 随机端口映射
  • -p: 指定端口映射
    • ip:hostPort:containerPort
    • ip::containerPort
    • hostPort:containerPort
    • containerPort

显示docker内容

docker ps查看docker里面的container

1
2
3
4
5
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6623ec31499b 7e6257c9f8d8 "/bin/bash" 6 minutes ago Exited (130) 3 minutes ago gallant_feynman
786aa38d950b hello-world "/hello" 19 hours ago Exited (0) 19 hours ago confident_allen
[root@localhost ~]#

常用参数

  • -a: 列出当前所有正在运行和历史上运行过的容器
  • -l: 列出最新创建的容器
  • -n: 显示最近n个创建的容器
  • -q: 静默模式,只显示容器编号
  • --no-trunc: 不截断输出

查看镜像layer

命令docker history image_id来查看镜像的layer数据

例子:

1
2
3
4
5
6
[root@localhost ~]# docker history 7e6257c9f8d8
IMAGE CREATED CREATED BY SIZE COMMENT
7e6257c9f8d8 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:61908381d3142ffba… 203MB
[root@localhost ~]#

启动容器

命令docker start [OPTIONS] CONTAINER [CONTAINER...]来启动已经停止的容器。
docker ps -a找出container id,然后再docker start container_id启动容器

重启容器

命令docker restart [OPTIONS] CONTAINER [CONTAINER...]来重启容器

停止容器

命令docker stop [OPTIONS] CONTAINER [CONTAINER...]来停止容器

强制关闭容器

命令docker kill [OPTIONS] CONTAINER [CONTAINER...]来强制停止容器

删除已停止的容器

命令docker rm [OPTIONS] CONTAINER [CONTAINER...]来删除容器
参数:

  • -f, --force: 强制删除容器,即使在运行中也会被删除。

用法:

  • 一次性删除所有容器
    • docker rm -f $(docker ps -a -q)
    • docker ps -q -q | xargs docker rm

容器退出

-it模式下

  • exit, 退出容器并关闭容器
  • ctrl + P + Q, 退出容器但不关闭容器

启动守护进程

命令docker run -d以守护进程来启动容器

注意:

  • Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(比如top,tail)等,容器会自动退出。
  • 所以使用docker来启动服务时,需要以前台方式进行。nginx为例,正常机器下,启动nginx的service即可,systemctl start nginx。但是在容器中,因为没有前台进程在运行,这种方式下docker会退出。

保存镜像到文件

命令docker save用于保存镜像到文件中。完整形式docker save [OPTIONS] IMAGE [IMAGE...]

用法:

1
docker save carl/mycentos7:latest > carl_mycentos7_latest.tar

从镜像文件导入镜像

命令docker load用于从镜像文件中导入镜像

用法:

1
docker load < carl_mycentos7_latest.tar

将容器导出为镜像文件

命令docker export用于将容器内容导出为镜像文件,docker export [OPTIONS] CONTAINER
docker save的区别是save是将image保存为文件,export是将容器保存为文件。

用法:

1
docker export 3a809727879b > carl_mycentos7_export.tar

将export导出的文件导入为文件

命令docker import将导出的tar文件导入为镜像。docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

用法:

1
docker import carl_mycentos7_export.tar carl/mycentos7:from_export

查看容器日志

docker logs -f -t --tail 容器ID
参数:

  • -t: 加入时间戳
  • -f: 跟随最新的日志打印
  • --tail: 数字,显示最后多少条

查看容器内进程

docker top CONTAINER查看某个container中的进程

查看容器内部细节

docker inspect NAME|ID, 查看容器的配置参数

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
[root@localhost ~]# docker inspect 859a0d5a0491
[
{
"Id": "859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6",
"Created": "2020-10-15T06:07:27.545519123Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true; do echo hello zzyy; sleep 2; done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 22951,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-10-15T06:07:27.784040202Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:7e6257c9f8d8d4cdff5e155f196d67150b871bbe8c02761026f803a704acb3e9",
"ResolvConfPath": "/var/lib/docker/containers/859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6/hostname",
"HostsPath": "/var/lib/docker/containers/859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6/hosts",
"LogPath": "/var/lib/docker/containers/859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6/859a0d5a0491dc3b8fb3e715b28c2e6374d17f7e55dd71f120fc8452b8ef81e6-json.log",
"Name": "/pensive_ride",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/b02579cda6e3f5050474b15434ec336589824f5a163bbeabebc39ad406c0f03a-init/diff:/var/lib/docker/overlay2/5010927575b48d2cd9437b03a5cb78a044a2a0a7796f0cc1d8592300afc700ea/diff",
"MergedDir": "/var/lib/docker/overlay2/b02579cda6e3f5050474b15434ec336589824f5a163bbeabebc39ad406c0f03a/merged",
"UpperDir": "/var/lib/docker/overlay2/b02579cda6e3f5050474b15434ec336589824f5a163bbeabebc39ad406c0f03a/diff",
"WorkDir": "/var/lib/docker/overlay2/b02579cda6e3f5050474b15434ec336589824f5a163bbeabebc39ad406c0f03a/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "859a0d5a0491",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"while true; do echo hello zzyy; sleep 2; done"
],
"Image": "centos:centos7",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20200809",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS",
"org.opencontainers.image.created": "2020-08-09 00:00:00+01:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "55b96a904a1cac67be763136b989b9c972223f80d7286184b1e0abc68a684692",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/55b96a904a1c",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "c14678728ac18495a503b0063c44f585ccdd6dd5f94097b8f2a4c337debd8832",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "5068459f90949c40739af743d9543bf327807d90f2bfa0e6362c7273570a0b47",
"EndpointID": "c14678728ac18495a503b0063c44f585ccdd6dd5f94097b8f2a4c337debd8832",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
[root@localhost ~]#

重新进入容器

docker attach CONTAINER 重新进入运行的容器
docker exec -t CONTAINER COMMAND,不进入容器运行命令。例如docker exec -t 8599f87085d7 ls -l /tmp/

从容器中拷贝文件到宿主机

命令docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
例子: docker cp 8599f87085d7:/tmp/yum.log ./

Docker镜像原理

UnionFS

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

镜像commit

docker commit -a "author name" -m "commit message" CONTAINER REPOSITORY[:TAG]将修改后的容器副本,使之成为一个新的镜像

例子
docker commit -a "carl" -m "repackage tomcat" 1238e0d02ff5 carl/tomcat:v1

容器数据卷

使用命令挂载数据卷

命令docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

例子:
docker run -it -v /myDataVolumn:/container_data_info centos:centos7 /bin/bash

挂载带读写权限,在容器内目录后面加上:ro, docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名

使用Dockerfile来挂载容器卷

可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]
说明:
出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。

  1. 编写Dockerfile

    1
    2
    3
    4
    5
    # volume test
    FROM centos:centos7
    VOLUME ["/dataVolumeContainer1", "/dataVolumeContainer2"]
    CMD echo "finished,==== success1"
    CMD /bin/bash
  2. docker build

docker build -f /mydocker/Dockerfile -t carl/centos7 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost mydocker]# docker build -f /mydocker/Dockerfile -t carl/centos7 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos:centos7
---> 7e6257c9f8d8
Step 2/4 : VOLUME ["/dataVolumeContainer1", "/dataVolumeContainer2"]
---> Running in 85a640f348d6
Removing intermediate container 85a640f348d6
---> a616037a068b
Step 3/4 : CMD echo "finished,==== success1"
---> Running in dc1542f6b493
Removing intermediate container dc1542f6b493
---> a9186d5923c6
Step 4/4 : CMD /bin/bash
---> Running in 2f116d647925
Removing intermediate container 2f116d647925
---> 54e2ebd7b090
Successfully built 54e2ebd7b090
Successfully tagged carl/centos7:latest
[root@localhost mydocker]#
  1. 查看构建的新images
    1
    2
    3
    4
    5
    6
    7
    8
    [root@localhost ~]# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    carl/centos7 latest 54e2ebd7b090 10 minutes ago 203MB
    carl/tomcat v1 45cab61abaa6 19 hours ago 652MB
    tomcat latest 891fcd9c5b3a 47 hours ago 647MB
    centos centos7 7e6257c9f8d8 2 months ago 203MB
    hello-world latest bf756fb1ae65 9 months ago 13.3kB
    [root@localhost ~]#

容器数据卷volumes-from

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

docker run时使用--volumes-from container_name_xx来挂载container_name_xx中的volume。
例子:
docker run -it --name dc02 --volumes-from dc01 carl/centos7, 即运行一个名为dc02的容器,并挂载来自dc01的卷。

结论: 容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

Dockfile解析

Dockerfile是什么

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

docker构三步骤:

  1. 手动编写一个dockerfile文件,要符合file的规范
  2. 有这个文件后,直接docker build命令执行,获得一个自定义的镜像
  3. run

Dockerfile构建过程解析

Dockerfile 内容基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. # 表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

docker执行Dockerfile的大致流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态。
    Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石

Dockerfile体系结构(保留字指令)

  • FROM: 基础镜像,当前镜像是基于哪个镜像的
  • MAINTAINER: 镜像维护者的姓名和邮箱地址
  • RUN: 容器构建时需要运行的命令
  • EXPOSE: 当前容器对外暴露出的端口
  • WORKDIR: 指定在创建容器后,终端默认登录的进来的工作目录
  • ENV: 用来在构建镜像过程中设置环境变量, 如ENV MY_PATH /usr/mypath
  • ADD: 将宿主机目录下的文件拷贝进镜像,且ADD命令会自动处理URL和解压tar压缩包
  • COPY:
    • 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件或目录复制到新一层的镜像内的<目录路径>的位置
    • 写法:
      • Shell写法: COPY src dst
      • JSON数组写法: COPY [“src”, “dst”]
  • VOLUME: 容器数据卷,用于数据保持和持久化工作
  • CMD: 指定一个容器启动时要运行的命令。Dockerfile中可以有多个CMD命令,但只有最后一个生效,CMD会被docker run之后的参数替换
  • ENTRYPOINT: 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序和参数,docker run的命令会添加到ENTRYPOINT的后面。
  • ONBUILD: 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发。

DockerFile案例,自定义镜像centos

Base镜像(scratch)

自定义镜像需求

  • 设置登录后的默认路径
  • 安装vim编辑器
  • 查看网络配置ifconfig支持
  1. 创建DockerFile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    FROM centos:centos7
    MAINTAINER xxxx<xxxx@yyy.com>
    ENV MYPATH /use/local
    WORKDIR $MYPATH
    RUN yum -y install vim
    RUN yum -y install net-tools
    EXPOSE 80
    CMD echo $MYPATH
    CMD echo "success--------ok"
    CMD /bin/bash
  2. 根据Dockerfil构建镜像
    docker build -t mycentos:1.3 .

  3. 根据创建好的镜像,运行容器

    1
    docker run -it mycentos:1.3
  4. 查看镜像历史

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [root@localhost ~]# docker history mycentos:1.3
    IMAGE CREATED CREATED BY SIZE COMMENT
    6099241fa296 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
    dcfbaf894d59 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
    6fd7a4095306 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
    707263299b11 4 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
    48d44a7faba4 4 minutes ago /bin/sh -c yum -y install net-tools 92.3MB
    ce4deda18898 4 minutes ago /bin/sh -c yum -y install vim 147MB
    db4e75c1541a 5 minutes ago /bin/sh -c #(nop) WORKDIR /use/local 0B
    5ec65a85b950 5 minutes ago /bin/sh -c #(nop) ENV MYPATH=/use/local 0B
    108c8029c6a5 5 minutes ago /bin/sh -c #(nop) MAINTAINER xxxx<xxxx@yyy.… 0B
    7e6257c9f8d8 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
    <missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
    <missing> 2 months ago /bin/sh -c #(nop) ADD file:61908381d3142ffba… 203MB
    [root@localhost ~]#

CMD/ENTRYPOINT镜像案例

CMD

  • CMD的命令会被docker run后添加的命令参数所覆盖。

ENTRYPOINT

  • docker run之后的参数会被当做参数传递给ENTRYPOINT, 之后形成新的命令组合

Dockerfile案例 – 自定义的tomcat9

Docker常用安装

安装mysql

1
2
3
4
5
6
7
8
9
# 虚拟机中启动mysql
docker pull mysql:5.6
docker run -p 12345:3306 --name mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
# 虚拟机中进入docker
docker exec -it 8810fbb3c2e6 /bin/bash
# 在最外层的mac下通过虚拟机映射的12345端口访问虚拟机运行的docker中的mysql
mysql -h 192.168.187.30 -uroot -P 12345 -p # 该命令在Mac下执行,192.168.187.30为虚拟机的IP

安装中遇到的问题
第一次docker run时,把密码写错写成了-e MYSQL_ROOT_PASSWORD=123455,然后进入到mysql的容器中mysql -uroot -p时输密码123456死活报ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)。把容器删了重新跑命令也不顶用。最后才反应过来,因为容器跑的时候添加了-v挂载配置文件的目录到宿主机上了。因此配置文件中设置的密码,一直都是第一次输错的密码123455, 把/zzyyuse/mysql目录下全部清掉,重新docker run后,就OK了。

一些要点

CMD 和 ENTRYPOINT的区别

Dockerfile中

  • CMD,会被命令行参数覆盖

    1
    2
    3
    4
    5
    6
    7
    # Dockerfile
    FROM Ubuntu
    CMD sleep 5
    # 命令行要修改sleep时间时,需要连命令一起带入
    docker run ubuntu-sleeper sleep 10
  • ENTRYPOINT的命令,一定会被执行,不会被命令行参数覆盖。

    1
    2
    3
    4
    5
    6
    7
    # Dockerfile
    FROM Ubuntu
    ENTRYPOINT ["sleep"]
    # 命令行执行时,加秒数即可
    docker run ubuntu-sleeper 10

Shell vs. Exec模式

推荐使用exec模式(JSON格式), Shell模式是先使用shell来调用命令,多一层调用,如果从外部发送任何POSIX信号到docker容器, 由于/bin/sh命令不会转发消息给实际运行的ping命令, 则不能安全得关闭docker容器(参考更详细的文档:Gracefully Stopping Docker Containers).
注意Exec模式,是不能获取$HOME等环境变量的,因为环境变量是shell相关的。

组合使用

组合使用ENTRYPOINT和CMD, ENTRYPOINT指定默认的运行命令, CMD指定默认的运行参数. 例子如下:

1
2
3
FROM ubuntu:trusty
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"]

则从外面可以修改CMD,但是/bin/ping -c 3被当做强行命令不能被命令行参数所修改。

强制修改Dockerfile中的entrypoint

使用--entrypoint参数来修改Dockerfile中的ENTRYPOINT命令
例子:

1
docker run --entrypoint sleep2.0 ubuntu-sleeper 10

在docker起来后,会执行命令sleep2.0 10

export 和save的区别

  1. 是否包含镜像历史
  • export 导出(import 导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。
  • save 保存(load 加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。
  1. 是否可以对镜像重命名
  • docker import 可以为镜像指定新名称
  • docker load 不能对载入的镜像重命名
  1. 是否可以同时将多个镜像打包到一个文件中
  • docker export 不支持
  • docker save 支持
  1. 是否包含容器修改
  • docker save是基于镜像的操作,因此容器中的修改内容不会体现到镜像文件中。
  • docker export是基于容器的操作,因此容器中所做的修改会体现到镜像文件中。

Docker 基础命令

docker run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 以交互方式运行名为nginx的image
docker run -it nginx '/bin/bash'
# 后台运行名为nginx:1.14-apline的image,并将container起名为webapp
docker run -d --name webapp nginx:1.14-alpine
# docker 绑定主机的80端口和容器的8080端口, TCP端口
docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
# 运行container并设置环境变量APP_COLOR=blue
docker run -d -p 38282:8080 --name blue-app -e APP_COLOR=blue image_name
# 指定network运行
docker run --name alpine-2 --network=none alpine
# 连接其他container运行
docker run --network=wp-mysql-network -e DB_Host=mysql-db -e DB_Password=db_pass123 -p 38080:8080 --name webapp --link mysql-db:mysql-db -d kodekloud/simple-webapp-mysql

获取某个container的环境变量

1
2
3
4
5
6
7
8
9
10
# 获取全部信息,手动查找
docker inspect container_name
# 逐行列出环境变量, 无论container是否在运行都可以使用
docker inspect -f \
'{{range $index, $value := .Config.Env}}{{println $value}}{{end}}' \
container_name | grep MYSQL_
# 打印出环境变量的值, container在运行时可用
docker exec container env

docker build

1
2
# 根据当前目录Dockerfile打包Image,命名为webapp-color
docker build -t webapp-color .

docker network create

1
2
3
4
5
6
7
8
9
10
11
# 查看docker network create的参数
docker network create -h
# 创建driver是bridge,网段是182.18.0.1、24,网关是182.18.0.1,名字是wp-mysql-network的网络
docker network create --driver bridge --subnet 182.18.0.1/24 --gateway 182.18.0.1 wp-mysql-network
# 查看创建的网络
docker network ls
# 查看网络的详情
docker network inspect wp-mysql-network

获取container网络有关的信息

1
docker inspect container_name -f "{{json .NetworkSettings.Networks }}"

Reference

留言