Docker 学习记录(二)
一、Docker 镜像详述
1.1 镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时的库、环境变量和配置文件。所有的应用直接打包成 docker 镜像,就可以直接跑起来。
获得镜像的方法:
- 从远程仓库下载
- 他人拷贝
- 自己制作
1.2 Docker 镜像相关原理
UnionFS(联合文件系统)
Union 文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层地叠加,同时可以将不同目录挂在到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker 镜像加载原理
Docker 镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包括 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上,包含的就是典型 Linux 系统中的 /dev、/proc、/bin、/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu、CentOS 等等。
- Docker 中的 CentOS 为什么这么小:对于一个精简的 OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以,因为底层直接用 Host 的kernel,自己只需要提供 rootfs就可以了。由此可见对于不同的 Linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发型版可以公用 bootfs。
1.3 分层理解
分层的镜像
下载的镜像一层一层的下载,如之前下载的 mysql 的日志过程为例:
~ % docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
12a06ca91af8: Pull complete
1fec1cb1944f: Pull complete
aede38c79379: Pull complete
51b980849561: Pull complete
f503d79ed4bc: Pull complete
6fb44db361f7: Pull complete
943b6dcee7de: Pull complete
911277c1fe4b: Pull complete
a477017d0457: Pull complete
84b5061403a5: Pull complete
5ff27d035d66: Pull complete
Digest: sha256:3d7ae561cf6095f6aca8eb7830e1d14734227b1fb4748092f2be2cfbccf7d614
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
分层结构的好处在于,资源共享!例如有多个镜像都从相同的 Base 镜像构建而来,那么宿主机只需要在磁盘上保留一份 Base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务,而且镜像的每一层都可以被共享。
查看镜像的分层通过使用 docker image inspect 镜像名
:
~ % docker image inspect centos
[
{
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d871dadfb37b53ef1ca45be04fc527562b91989991a8f545345ae3be0b93f92a"
]
},
分析:
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或者增加内容时,就会在当前镜像层之上,创建新的镜像层。如以下图中的例子,基于 Ubuntu 16.04 创建一个新的镜像,这就是镜像的第一层,如果在该镜像中添加 python 包,就会在基础镜像层上创建第二个镜像层,如果再添加一个安全补丁,就会创建第三个镜像层。
在添加额外的镜像层的同时,镜像始终保持当前所有镜像的组合,下图中展示的是一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,因为最上层中的文件7是文件5的一个更新版。
这种情况下,上层镜像层中的文件覆盖了底层镜像层的文件,这样就使得文件的更新版本作为一个新的镜像层添加到镜像当中,Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。下图展示了与系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。
特点:Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们常说的容器层,容器之下都叫镜像层。
二、实战打包一个新的镜像
2.1 部署 tomcat
# 下载 tomcat 镜像
~ % docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
94a23d3cb5be: Pull complete
ac9d381bd1e9: Pull complete
aa9c5b49b9db: Pull complete
841dd868500b: Pull complete
42dee876d816: Pull complete
c4851c976ae9: Pull complete
e80a0433b650: Pull complete
e10afb8c99ce: Pull complete
7870523e466f: Pull complete
Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest
~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest b64abfdee99c 13 months ago 668MB
docker/getting-started latest 720f449e5af2 14 months ago 27.2MB
centos latest e6a0117ec169 16 months ago 272MB
# 启动 tomcat 镜像 暴露端口为8080
~ % docker run -d -p 8080:8080 --name tomcat1 tomcat
cc21a207133db346be97f7fa0f3300421134232bbf6624e03a3653ed00796d6a
此时我们的tomcat已经启动成功,访问本地 localhost:8080 地址,可以得到如下页面,由于该镜像内容并不完整,会出现这样的页面,但是这说明我们的 tomcat 已经部署成功。
接下来,我们将它完善一下
# 查看镜像信息
~ % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc21a207133d tomcat "catalina.sh run" 11 minutes ago Up 11 minutes 0.0.0.0:8080->8080/tcp tomcat1
# 进入镜像中查看内容
~ % docker exec -it cc21a207133d /bin/bash
root@cc21a207133d:/usr/local/tomcat# ls
BUILDING.txt NOTICE RUNNING.txt lib temp work
CONTRIBUTING.md README.md bin logs webapps
LICENSE RELEASE-NOTES conf native-jni-lib webapps.dist
root@cc21a207133d:/usr/local/tomcat# cd webapps
root@cc21a207133d:/usr/local/tomcat/webapps# ls
root@cc21a207133d:/usr/local/tomcat#
# 我们发现 webapps 文件夹下没有任何文件,文件都在 webapps.dist 下,将内容都拷贝进 webapps 中
root@cc21a207133d:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@cc21a207133d:/usr/local/tomcat# cd webapps
root@cc21a207133d:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
现在我们已经将它完善部署成功了,我们重新访问本地 localhost:8080 地址,就能得到这样的页面,说明已经完善成功。
2.2 Commit 提交自己的镜像
将我们完善好的 tomcat 镜像打包成新的镜像,使用的命令为docker commit
。
docker commit -m="提交的描述信息" -a="作者信息" 容器ID 目标镜像名:[TAG]
# 打包镜像
~ % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc21a207133d tomcat "catalina.sh run" 30 minutes ago Up 30 minutes 0.0.0.0:8080->8080/tcp tomcat1
~ % docker commit -m="add webapps app" -a="sihengshen" cc21a207133d tomcat2:1.0
sha256:da365a5106011f1d3bb8a205527de1e73b287480dc6e91f8c41392bd569647c6
~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat2 1.0 da365a510601 43 seconds ago 673MB # 这是我们自己打包的镜像
tomcat latest b64abfdee99c 13 months ago 668MB
docker/getting-started latest 720f449e5af2 14 months ago 27.2MB
centos latest e6a0117ec169 16 months ago 272MB
至此,我们就完成了实战打包镜像的过程。
三、容器数据卷
3.1 命令挂载
容器数据卷的概念:如果数据存在容器之中,那么我们删除容器数据就会丢失,例如使用 Mysql数据库,删了容器之后数据库就没了,若要保证不会出现删库跑路的情况,就需要容器之间有一个数据共享的技术,即 Docker 容器中的数据同步到本地。
使用数据卷的方法:
docker run -it -v 主机目录地址:容器内目录地址
# 测试 将 CentOS 容器的目录 /home 挂载在 本机目录 /home/ceshi下
docker run -it -v /home/ceshi:/home centos /bin/bash
# 通过 docker inspect 容器ID
至此,我们就完成了目录的搭载,能够保证容器内容不会丢失,我们需要修改内容只需要在本地修改,容器内会自动同步,还有一个Mysql的实战大家可以自己尝试。
具名挂载和匿名挂载:是否在
-v
后添加卷名称,查看数据卷相关操作可以使用docker volume --help
查看。# 匿名挂载 docker -v 容器内路径 # 具名挂载 docker -v 卷名:容器内路径 # 指定路径挂载 docker -v 宿主机路径:容器内路径
读写权限:docker run -d -P -v name:路径:ro/rw
ro
:readonly——只读
rw
:readwrite——可读可写
3.2 Dockerfile 挂载
Dockerfile 就是用来构建 docker 镜像的构建文件,命令脚本,通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层。
先编写一个 Dockerfile 文件,然后构建镜像。
# 创建一个 dockerfile 文件,名字建议为 Dockerfile
# 文件中所有内容指令大写
~ % cat Dockerfile
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "---end---"
CMD /bin/bash
# 构建镜像
~ % docker build -f ./Dockerfile -t centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
a1d0c7532777: Already exists
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01", "volume02"]
---> Running in b7e68fd690d9
Removing intermediate container b7e68fd690d9
---> 3e2806f7944b
Step 3/4 : CMD echo "---end---"
---> Running in 6689c2dd857b
Removing intermediate container 6689c2dd857b
---> 5978d9517c38
Step 4/4 : CMD /bin/bash
---> Running in 048dd2705ef4
Removing intermediate container 048dd2705ef4
---> d6430d99300d
Successfully built d6430d99300d
Successfully tagged centos:1.0
~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 1.0 d6430d99300d 2 minutes ago 231MB
这种方法是匿名挂载,这种方式我们未来使用特别多,如果构建镜像的时候没有挂载数据卷,就需要使用-v 卷名:容器内路径
手动挂载。
3.3 数据卷容器
能够实现两个或者多个容器之间数据共享,使用命令--volume-from 容器名
。容器之间配置信息的传递,数据卷容器的生命一直持续到没有容器使用为止。但是一旦持久化到了本地,即将数据挂载到本地,本地数据就是不会删除的。
四、Dockerfile
4.1 Dockerfile 介绍
在上一小节中,我们初步的认识了一下 Dockerfile,它是用来构建 docker 镜像的文件,命令参数脚本。具体构建步骤为:
- 编写一个 dockerfile 文件;
docker build
构建成为一个镜像;docker run
运行镜像;docker push
发布镜像(DockerHub、阿里云镜像仓库)。
4.2 Dockerfile 构建过程
基础内容
- 所有保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
#
表示注释- 每个指令都会创建提交一个新的镜像层并提交
Dockerfile 是面向开发的,之后需要发布项目做镜像,就需要通过编写 Dockerfile 文件。Docker 镜像逐渐成为企业交付的标准。开发、部署、运维缺一不可。
- Dockerfile:构建文件,定义了一切的步骤,源代码;
- Docker 镜像:通过 Dockerfile 构建生成的镜像,最终发布和运行的产品;
- Docker 容器:容器就是镜像运行起来提供服务的。
4.3 Dockerfile 指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名 + 邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 添加内容
WORKDIR # 镜像的工作目录
EXPOSE # 暴露端口设置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 Dockerfile 这个时候就会运行 ONBUILD 命令。触发指令
COPY # 类似 ADD,将文锦啊拷贝到镜像中
ENV # 构建的时候设置环境变量
4.4 实战测试
4.4.1 实战一:构建自己的 CentOS
之前都是使用别人搭建好的镜像,现在我们动手实战构建一个尝试一下。Docker Hub 中99%的镜像都是从FROM scratch
这个基础镜像过来的,然后配置需要的软件和配置来进行构建。
- 编写 Dockerfile
~ % cat Dockerfile
FROM centos
MAINTAINER Mark<sihengshen@foxmail.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN cd /etc/yum.repos.d/ \
&& sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \
&& sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \
&& yum makecache \
&& yum update -y \
&& yum -y install vim \
&& yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end-----"
CMD /bin/bash
⚠️注意: 如果按照视频中编写 Dockerfile,会出现如下报错信息Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist
,这是因为 CentOS 已经停止维护。因此需要进行相应的修改,上述内容是修改后可以成功运行的内容。
- 通过这个文件构建镜像
# 构建命令 docker build -f Dockerfile文件路径 -t 镜像名:[tag]
~ % docker build -f Dockerfile -t centosplus:latest .
...
Successfully built d19008ae7207
Successfully tagged centosplus:latest
这样就说明构建成功。
⚠️注意: 镜像构建成功后,使用docker images
命令查看,发现很多<none>:<none>的镜像,这样的镜像可能有用,有用的镜像是由于镜像分层的中间镜像。它们只会在docker images -a才会显示出来,用docker images是不会显示的。它们也不会造成占用磁盘空间问题;也可能无用,无用的镜像会占用空间,主要是由于新加镜像替换原来相对标签的镜像,原来镜像就变成了<none>:<none>而没有被删除,无用的镜像可以使用命令docker rmi $(docker images -f "dangling=true" -q)
删除。
- 验证一下
~ % docker run -it centosplus
[root@4884d292c133 local]# pwd
/usr/local
[root@4884d292c133 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@4884d292c133 local]# nano
验证成功,我们需要安装的内容已经成功安装。
补充: 我们还可以通过命令docker history 镜像ID
查看镜像的构建步骤。
4.4.2 CMD 和 ENTRYPOINT 的区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
- 测试 CMD
# 编写 Dockerfile 文件
~ % cat cmd-Dockerfile
FROM centos
CMD ["ls", "-a"]
# 构建镜像
~ % docker build -f cmd-Dockerfile -t cmdcentos:latest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls", "-a"]
---> Running in f38ad3f00d47
Removing intermediate container f38ad3f00d47
---> ed9e59c253f4
Successfully built ed9e59c253f4
Successfully tagged cmdcentos:latest
# 运行镜像,我们的命令 ls -a 生效
~ % docker run ed9e59c253f4
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加命令 -l,成为 ls -al
~ % docker run ed9e59c253f4 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0001] error waiting for container: context canceled
# CMD 指令下,是直接替换上一个命令,因此会报错,如下运行就可以实现
~ % docker run ed9e59c253f4 ls -al
total 56
drwxr-xr-x 1 root root 4096 Feb 1 06:29 .
drwxr-xr-x 1 root root 4096 Feb 1 06:29 ..
-rwxr-xr-x 1 root root 0 Feb 1 06:29 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Feb 1 06:29 dev
drwxr-xr-x 1 root root 4096 Feb 1 06:29 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 123 root root 0 Feb 1 06:29 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Feb 1 06:29 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
- 测试 ENTRYPOINT
# 编写 Dockerfile 文件
~ % cat cmd-Dockerfile
FROM centos
ENTRYPOINT ["ls", "-a"]
# 构建镜像
~ % docker build -f entrypoint-Dockerfile -t entcentos:latest .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Running in 55fd70dc9072
Removing intermediate container 55fd70dc9072
---> dbee450e5e1f
Successfully built dbee450e5e1f
Successfully tagged entcentos:latest
# 运行镜像,我们的命令 ls -a 生效
~ % docker run dbee450e5e1f
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 使用了
~ % docker run dbee450e5e1f -l
total 56
drwxr-xr-x 1 root root 4096 Feb 1 06:41 .
drwxr-xr-x 1 root root 4096 Feb 1 06:41 ..
-rwxr-xr-x 1 root root 0 Feb 1 06:41 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Feb 1 06:41 dev
drwxr-xr-x 1 root root 4096 Feb 1 06:41 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 123 root root 0 Feb 1 06:41 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Feb 1 06:29 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
4.4.3 实战二:部署 tomcat
现在我们来部署一个更复杂的镜像,自己构建一个 tomcat 镜像并部署。
- 准备压缩包
我们需要先在服务器中新建一个文件夹 tomcat,并准备好两个压缩包:apache-tomcat-8.0.23.tar.gz
和jdk-8u131-linux-x64.tar.gz
,下面是如何在服务器利用命令下载压缩包的方式。
- tomcat 压缩包:使用命令
wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.23/bin/apache-tomcat-8.0.23.tar.gz
下载; - jdk 压缩包:去官网搜索相关压缩包,登录后复制下载链接,因为不花时间再登录了,就复制了一个别人的下载链接,直接使用命令
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
就能下载成功。
此刻我们的压缩包已经准备完成。
~/tomcat % ls
apache-tomcat-8.0.23.tar.gz jdk-8u131-linux-x64.tar.gz
- 编写 Dockerfile 文件
~/tomcat % cat Dockerfile
FROM centos
MAINTAINER siheng<sihengshen@foxmail.com>
COPY README.md /usr/local/README.md
ADD jdk-8u131-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.0.23.tar.gz /usr/local/
RUN cd /etc/yum.repos.d/ \
&& sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \
&& sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \
&& yum makecache \
&& yum update -y \
&& yum -y install nano
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_131
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools/jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.0.23
ENV CATALINA_BASH /usr/local/apache-tomcat-8.0.23
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.0.23/bin/startup.sh && tail -F /url/local/apache-tomcat-8.0.23/bin/logs/catalina.out
- 构建镜像
~/tomcat % docker build -t diytomcat .
- 启动镜像
使用命令docker run -d -p 8082:8080 --name sihengtomcat -v /root/ssh/tomcat/test:/usr/local/apache-tomcat-8.0.23/webapps/test -v /root/ssh/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.0.23/logs diytomcat
启动容器,其中对应暴露端口以及挂载目录。运行后测试访问8082端口成功。
- 发布项目
因为我们做了挂载目录的操作,因此只需要在本机的/root/ssh/tomcat/test
目录下发布项目内容即可。首先在其中创建一个 index.html 文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>tomcat</title>
</head>
<body>
<h1>
我自己的第一个tomcat镜像!
</h1>
</body>
</html>
然后访问8082端口的 test 目录,测试成功。
综上,我们以后开发的过程中,只要部署成功即可直接访问。
4.5 发布镜像
发布到 Docker Hub
- 注册一个 Docker Hub 账号;
- 在服务器使用命令
docker login -u 用户名
登录账号,然后输入密码,密码正确即可登录成功; - 发布之前使用命令
docker tag 用户名/镜像名:[tag]
修改要发布的镜像标签,然后使用命令docker push 用户名/镜像名:[tag]
发布镜像。
发布到阿里云镜像仓库
- 登录到阿里云,进入控制台,选择容器镜像服务
- 创建相关内容
如果是第一次使用,需要经过以下步骤:
- 创建个人实例
- 创建命名空间
- 创建镜像仓库:填写相关内容,选择本地仓库为代码源。
仓库创建成功后,点击进去可以看到对应的推送操作,按照过程执行命令即可。