Docker dockerfile构建镜像与network实践

字数: 5700

Dockerfile 实践

Dockerfile 模板

Dockerfile 有很多命令,但是常用的就下边这些

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 引用基础镜像
FROM 基础镜像:标签
# 给镜像添加备注
LABEL REMARK="测试使用"
# 给镜像添加环境变量
ENV PATH $PATH:/usr/local/bin
    APP_HOME=/home/app
# 添加主机目录到容器目录
ADD . /home
# 执行指令
RUN 命令1 \
    && 命令2 \
    && 命令3 && 命令4
# 设置镜像的主目录
WORKDIR /home/app
# 启动容器时执行的命令, 比如 CMD /bin/bash
CMD 命令

构建思路

其实就是相当于手动在 Centos 里安装应用的过程,只不过这个过程由 Dockerfile 命令自动化进行了。

所以在构建 Dockerfile 之前,需要先了解需要安装的应用,它到底怎么安装,这个安装的过程是怎么样的。

实践一:以 anolisos 为基础镜像,构建 tomcat 镜像

anolisos 是阿里开源的一个国产 Linux 系统

拉取 anolisos 镜像

1
[root@status docker]# docker pull registry.openanolis.cn/openanolis/anolisos:8

进入 anolisos 镜像

1
[root@status docker]# docker run -it --name anolisos registry.openanolis.cn/openanolis/anolisos:8 /bin/bash

进入里边发现一个问题,就是 tomcat 包从哪里来?

  • 使用 Yum 源下载(不推荐,自己的玩具项目可以)
  • 放一个到本地,然后使用 ADD 或者 COPY 指令,添加到容器中(使用这个)

配置 JDK 并安装 tomcat

1)安装 JDK

因为基础镜像中一切从简,默认是没有 JDK 的,所以需要安装

1
yum install -y java-1.8.0-openjdk

2)查看 JDK 的安装目录

1
2
3
4
5
6
[root@ae813af28fd9 /]# whereis java
java: /usr/bin/java /usr/lib/java /etc/java /usr/share/java /usr/share/man/man1/java.1.gz
[root@ae813af28fd9 /]# ls -l /usr/bin/java 
lrwxrwxrwx 1 root root 22 Sep 18 01:49 /usr/bin/java -> /etc/alternatives/java
[root@ae813af28fd9 /]# ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 75 Sep 18 01:49 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.0.2.an8.x86_64/jre/bin/java

JDK 的安装目录就是 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.0.2.an8.x86_64/jre/bin/java

3)配置环境变量

1
2
3
4
5
6
vi ~/.bash_profile
# 加入
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.0.2.an8.x86_64/jre
export PATH=$JAVA_HOME/bin:$PATH
# 刷新环境变量
source ~/.bash_profile

4)安装 tomcat

5)启动 tomcat

根据操作步骤编写 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
# 基于基础镜像
FROM registry.openanolis.cn/openanolis/anolisos:8

LABEL Author="test"
LABEL Remark="测试使用, 基于 anolisos 制作 Tomcat 镜像"

# 配置 JDK 环境变量
ENV JAVA_HOME /home/tomcat/jre
ENV PATH $JAVA_HOME/bin:$PATH

# 创建一个目录存放 JDK 和 tomcat 安装包,注意顺序,得先有这个目录,后续才能放到这个目录
RUN mkdir -p /home/tomcat

# 设置 tomcat 主目录 如果后边的命令不需要基于这个主目录去执行,也可不设置
WORKDIR /home/tomcat

# 添加 JDK 包和 tomcat 包到容器内部,确保包和 dockerfile 都在一个目录下
# ADD 命令会自动将 tar 包解压
ADD jdk.tar.gz /home/tomcat
ADD apache-tomcat-10.1.30.tar.gz /home/tomcat

# 暴露端口
EXPOSE 8080
# 启动 tomcat
CMD ["/home/tomcat/apache-tomcat-10.1.30/bin/catalina.sh","run"]

使用 Dockerfile 构建镜像

注意:Dockerfile 与 JDK \ tomcat 的 tar 包要处于同一个目录下

 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
[root@status dockerfile]# docker build -t test:v1 .
Sending build context to Docker daemon 65.99 MB
Step 1/11 : FROM registry.openanolis.cn/openanolis/anolisos:8
 ---> ef65d5c9c386
Step 2/11 : LABEL Author "test"
 ---> Running in 3f756590b7cd
 ---> 27aab3b7f5b3
Removing intermediate container 3f756590b7cd
Step 3/11 : LABEL Remark "测试使用, 基于 龙蜥系统 制作 Tomcat 镜像"
 ---> Running in b5fc72ee8fac
 ---> 68a7c28837a0
Removing intermediate container b5fc72ee8fac
Step 4/11 : ENV JAVA_HOME /home/tomcat/jre
 ---> Running in 1136456bdb18
 ---> 0ea43384acec
Removing intermediate container 1136456bdb18
Step 5/11 : ENV PATH $JAVA_HOME/bin:$PATH
 ---> Running in 598616ebc31f
 ---> ddbc3d112a6b
Removing intermediate container 598616ebc31f
Step 6/11 : RUN mkdir -p /home/tomcat
 ---> Running in 9fb8f361d189

 ---> 621e6817887f
Removing intermediate container 9fb8f361d189
Step 7/11 : WORKDIR /home/tomcat
 ---> 1a893a18a343
Removing intermediate container 009c81d31fc1
Step 8/11 : ADD jdk.tar.gz /home/tomcat
 ---> 92064443362d
Removing intermediate container de35da461b5d
Step 9/11 : ADD apache-tomcat-10.1.30.tar.gz /home/tomcat
 ---> 006acfe8ee17
Removing intermediate container b5d3283e5c4a
Step 10/11 : EXPOSE 8080
 ---> Running in 5460b8f751fb
 ---> 9f59ded402c3
Removing intermediate container 5460b8f751fb
Step 11/11 : CMD /home/tomcat/apache-tomcat-10.1.30/bin/catalina.sh run
 ---> Running in 99352d2ca9f8
 ---> 56c59b8f7d84
Removing intermediate container 99352d2ca9f8
Successfully built 56c59b8f7d84

成功了,可以看看这个镜像的信息

1
2
3
[root@status dockerfile]# docker images
REPOSITORY                                   TAG                 IMAGE ID            CREATED              SIZE
test                                         v1                  1ae021027b9c        About a minute ago   386 MB
1
docker inspect test:v1

启动镜像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@status dockerfile]# docker run -it --name tomcat_aliyun -p 8080:8080 test:v1 
Using CATALINA_BASE:   /home/tomcat/apache-tomcat-10.1.30
Using CATALINA_HOME:   /home/tomcat/apache-tomcat-10.1.30
Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-10.1.30/temp
Using JRE_HOME:        /home/tomcat/jre
Using CLASSPATH:       /home/tomcat/apache-tomcat-10.1.30/bin/bootstrap.jar:/home/tomcat/apache-tomcat-10.1.30/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Unrecognized option: --add-opens=java.base/java.lang=ALL-UNNAMED
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

这里启动 tomcat 报错了

具体原因:解决ideatomcatUnrecognized option:–add-opens=java.base/java.lang=ALL-UNNAMEDError:Could not create th_unrecognized option: –add-opens-CSDN博客

反正就是 JDK1.8.0 与 tomcat10 不匹配,把 tomcat 版本降一下,换成 tomcat9

换了 tomcat9 又报错了

1
Caused by: java.lang.Error: java.io.FileNotFoundException: /home/tomcat/jre/lib/tzdb.dat (No such file or directory)

在 dockerfile 里配置一下 jre_home 环境变量

重新调整 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
# 基于anolisos
FROM registry.openanolis.cn/openanolis/anolisos:8

LABEL Author="test"
LABEL Remark="测试使用, 基于 anolisos 制作 Tomcat 镜像"

# 配置 JDK 环境变量
ENV JAVA_HOME /home/tomcat/jdk1.8.0_202
ENV JRE_HOME /home/tomcat/jdk1.8.0_202/jre
ENV CLASSPATH $JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH $JAVA_HOME/bin:$PATH

# 创建一个目录存放 JDK 和 tomcat 安装包,注意顺序,得先有这个目录,后续才能放到这个目录
RUN mkdir -p /home/tomcat

# 设置 tomcat 主目录 如果后边的命令不需要基于这个主目录去执行,也可不设置
WORKDIR /home/tomcat

# 添加 JDK 包和 tomcat 包到容器内部,确保包和 dockerfile 都在一个目录下
# ADD 命令会自动将 tar 包解压
ADD jdk-8u202-linux-i586.tar.gz /home/tomcat
ADD apache-tomcat-9.0.95.tar.gz /home/tomcat

# 暴露端口
EXPOSE 8080
# 启动 tomcat
CMD ["/home/tomcat/apache-tomcat-9.0.95/bin/catalina.sh","run"]

使用这个 dockerfile 构建镜像

然后启动它

还是报错了

1
2
3
4
5
6
7
8
[root@status dockerfile]# docker run -it --name tomcat_aliyun -p 8080:8080 test:v1
Using CATALINA_BASE:   /home/tomcat/apache-tomcat-9.0.95
Using CATALINA_HOME:   /home/tomcat/apache-tomcat-9.0.95
Using CATALINA_TMPDIR: /home/tomcat/apache-tomcat-9.0.95/temp
Using JRE_HOME:        /home/tomcat/jdk1.8.0_202/jre
Using CLASSPATH:       /home/tomcat/apache-tomcat-9.0.95/bin/bootstrap.jar:/home/tomcat/apache-tomcat-9.0.95/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
/home/tomcat/apache-tomcat-9.0.95/bin/catalina.sh: line 421: /home/tomcat/jdk1.8.0_202/jre/bin/java: No such file or directory

感觉是这个 JDK 版本不匹配,重新下一个 x64 版本的 jdk

最终调整 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
# 基于anolisos
FROM registry.openanolis.cn/openanolis/anolisos:8

LABEL Author="test"
LABEL Remark="测试使用, 基于 anolisos 制作 Tomcat 镜像"

# 创建一个目录存放 JDK 和 tomcat 安装包,注意顺序,得先有这个目录,后续才能放到这个目录
RUN mkdir -p /home/tomcat

# 添加 JDK 包和 tomcat 包到容器内部,确保包和 dockerfile 都在一个目录下
# ADD 命令会自动将 tar 包解压
ADD jdk-8u202-linux-x64.tar.gz /home/tomcat
ADD apache-tomcat-9.0.95.tar.gz /home/tomcat

# 设置 tomcat 主目录 如果后边的命令不需要基于这个主目录去执行,也可不设置
WORKDIR /home/tomcat

# 配置 JDK 环境变量
ENV JAVA_HOME /home/tomcat/jdk1.8.0_202
ENV JRE_HOME /home/tomcat/jdk1.8.0_202/jre
ENV CLASSPATH /home/tomcat/jdk1.8.0_202/lib:/home/tomcat/jdk1.8.0_202/jre/lib
ENV PATH $JAVA_HOME/bin:$PATH

# 验证一下 JDK 是否配置
RUN $JAVA_HOME/bin/java -version

# 暴露端口
EXPOSE 8080
# 启动 tomcat
CMD ["/home/tomcat/apache-tomcat-9.0.95/bin/catalina.sh","run"]

构建过程:

 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
[root@status dockerfile]# docker build test:v1 .
"docker build" requires exactly 1 argument(s).
See 'docker build --help'.

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile
[root@status dockerfile]# docker build -t test:v1 .
Sending build context to Docker daemon 206.8 MB
Step 1/14 : FROM registry.openanolis.cn/openanolis/anolisos:8
 ---> ef65d5c9c386
Step 2/14 : LABEL Author "test"
 ---> Running in ec01334f21ac
 ---> 88b417c6fcff
Removing intermediate container ec01334f21ac
Step 3/14 : LABEL Remark "测试使用, 基于 龙蜥系统 制作 Tomcat 镜像"
 ---> Running in efbab43c84cf
 ---> f64ab9b3ca4b
Removing intermediate container efbab43c84cf
Step 4/14 : RUN mkdir -p /home/tomcat
 ---> Running in 0bd99be045f6

 ---> 4535e994046e
Removing intermediate container 0bd99be045f6
Step 5/14 : ADD jdk-8u202-linux-x64.tar.gz /home/tomcat
 ---> 103c0a0d137d
Removing intermediate container 778a257c323e
Step 6/14 : ADD apache-tomcat-9.0.95.tar.gz /home/tomcat
 ---> 6e3b3068a3f6
Removing intermediate container 4860b4330b7c
Step 7/14 : WORKDIR /home/tomcat
 ---> 4a6354a3c4ca
Removing intermediate container 2f3bf66b733c
Step 8/14 : ENV JAVA_HOME /home/tomcat/jdk1.8.0_202
 ---> Running in a02da957f0e5
 ---> fbb98637fc47
Removing intermediate container a02da957f0e5
Step 9/14 : ENV JRE_HOME /home/tomcat/jdk1.8.0_202/jre
 ---> Running in 15a12e697856
 ---> 576b7678f857
Removing intermediate container 15a12e697856
Step 10/14 : ENV CLASSPATH /home/tomcat/jdk1.8.0_202/lib:/home/tomcat/jdk1.8.0_202/jre/lib
 ---> Running in 28af34ebfcff
 ---> d87b8a7680af
Removing intermediate container 28af34ebfcff
Step 11/14 : ENV PATH $JAVA_HOME/bin:$PATH
 ---> Running in 440870ff6cbf
 ---> eb633e75c31b
Removing intermediate container 440870ff6cbf
Step 12/14 : RUN $JAVA_HOME/bin/java -version
 ---> Running in b888421b5460
 
# 注意看这里 #################
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
##############################

 ---> 585c6ee10358
Removing intermediate container b888421b5460
Step 13/14 : EXPOSE 8080
 ---> Running in fa69ece8e180
 ---> c4af6c5056bc
Removing intermediate container fa69ece8e180
Step 14/14 : CMD /home/tomcat/apache-tomcat-9.0.95/bin/catalina.sh run
 ---> Running in 2a007a3fd78f
 ---> e184d618916b
Removing intermediate container 2a007a3fd78f
Successfully built e184d618916b

看着应该没问题

启动镜像看看

 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
[root@status dockerfile]# docker run -d --name test_tomcat -p 8080:8080 test:v1
d14c7820921dd0150c1d4c9e9ff786164201f10f86c7dc63db6522ded8b2405a
[root@status dockerfile]# docker ps 
CONTAINER ID        IMAGE                                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
d14c7820921d        test:v1                                        "/home/tomcat/apac..."   7 seconds ago       Up 6 seconds        0.0.0.0:8080->8080/tcp   test_tomcat
ae813af28fd9        registry.openanolis.cn/openanolis/anolisos:8   "/bin/bash"              5 hours ago         Up 5 hours                                   anolisos
[root@status dockerfile]# docker logs test_tomcat 
18-Sep-2024 07:16:34.224 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/9.0.95
18-Sep-2024 07:16:34.246 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Sep 13 2024 18:07:47 UTC
18-Sep-2024 07:16:34.247 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.95.0
18-Sep-2024 07:16:34.247 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            3.10.0-1160.118.1.el7.x86_64
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /home/tomcat/jdk1.8.0_202/jre
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_202-b08
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
18-Sep-2024 07:16:34.248 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /home/tomcat/apache-tomcat-9.0.95
18-Sep-2024 07:16:34.249 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /home/tomcat/apache-tomcat-9.0.95
18-Sep-2024 07:16:34.263 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-9.0.95/conf/logging.properties
18-Sep-2024 07:16:34.263 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
18-Sep-2024 07:16:34.263 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
18-Sep-2024 07:16:34.263 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
18-Sep-2024 07:16:34.264 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
18-Sep-2024 07:16:34.264 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs=
18-Sep-2024 07:16:34.265 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/home/tomcat/apache-tomcat-9.0.95
18-Sep-2024 07:16:34.265 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/home/tomcat/apache-tomcat-9.0.95
18-Sep-2024 07:16:34.265 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/home/tomcat/apache-tomcat-9.0.95/temp
18-Sep-2024 07:16:34.284 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The Apache Tomcat Native library which allows using OpenSSL was not found on the java.library.path: [/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib]
18-Sep-2024 07:16:35.498 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
18-Sep-2024 07:16:35.604 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [2074] milliseconds
18-Sep-2024 07:16:35.719 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
18-Sep-2024 07:16:35.720 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.95]
18-Sep-2024 07:16:35.749 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/host-manager]
18-Sep-2024 07:16:36.660 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/host-manager] has finished in [910] ms
18-Sep-2024 07:16:36.661 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/docs]
18-Sep-2024 07:16:36.750 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/docs] has finished in [89] ms
18-Sep-2024 07:16:36.751 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/examples]
18-Sep-2024 07:16:37.540 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/examples] has finished in [789] ms
18-Sep-2024 07:16:37.540 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/ROOT]
18-Sep-2024 07:16:37.641 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/ROOT] has finished in [100] ms
18-Sep-2024 07:16:37.642 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/manager]
18-Sep-2024 07:16:37.730 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/tomcat/apache-tomcat-9.0.95/webapps/manager] has finished in [87] ms
18-Sep-2024 07:16:37.767 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
18-Sep-2024 07:16:37.799 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [2194] milliseconds

看着启动起来了

访问 tomcat 前台看看,没问题了

总结

编写 dockerfile 的思路,其实就是实际手动配置的思路。

就以构建 tomcat 镜像来说,如果是手工操作:

  • 需要准备 JDK、tomcat 包
  • 需要解压 JDK、tomcat 包
  • 需要配置 JDK 的环境变量
  • 需要开通 tomcat 的 8080 端口

在编写 dockerfile 的时候,也是同理:

  • 准备好的 JDK、tomcat 包放到镜像的什么地方?
  • ADD 指令会自动解压 JDK、tomcat 包,代替了手动执行 tar 命令
  • 配置 JDK 的环境变量
  • 暴露 tomcat 的 8080 端口
  • 最后,使用 CMD 指令,执行启动 tomcat 的命令

还有就是,一定得注意 tomcat 版本应该与 JDK 版本相匹配。

实践二:以 anolisos 为基础镜像,构建 nginx 镜像

还是以 anolisos 为基础镜像,并在里边运行一个 nginx 服务。

安装 nginx

根据此文

Linux 安装 Nginx 并配置为系统服务(超详细)-阿里云开发者社区 (aliyun.com)

1)下载 nginx 并解压

1
2
wget http://nginx.org/download/nginx-1.25.1.tar.gz
tar -xzvf nginx-1.25.1.tar.gz /home/dockerfile_nginx

2)配置 nginx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
./configure

# 出现下边表示成功
Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + md5: using system crypto library
  + sha1: using system crypto library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

一般来讲,还是需要安装 gcc 之类的依赖的,因为我这个是阿里云服务器,里边的内容都比较完整,可以直接配置。

3)编译安装

 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
make && make install

# 出现下边这个
make -f objs/Makefile install
make[1]: Entering directory `/home/dockerfile_nginx/nginx-1.9.9'
test -d '/usr/local/nginx' || mkdir -p '/usr/local/nginx'
test -d '/usr/local/nginx/sbin'                 || mkdir -p '/usr/local/nginx/sbin'
test ! -f '/usr/local/nginx/sbin/nginx'                 || mv '/usr/local/nginx/sbin/nginx'                     '/usr/local/nginx/sbin/nginx.old'
cp objs/nginx '/usr/local/nginx/sbin/nginx'
test -d '/usr/local/nginx/conf'                 || mkdir -p '/usr/local/nginx/conf'
cp conf/koi-win '/usr/local/nginx/conf'
cp conf/koi-utf '/usr/local/nginx/conf'
cp conf/win-utf '/usr/local/nginx/conf'
test -f '/usr/local/nginx/conf/mime.types'              || cp conf/mime.types '/usr/local/nginx/conf'
cp conf/mime.types '/usr/local/nginx/conf/mime.types.default'
test -f '/usr/local/nginx/conf/fastcgi_params'          || cp conf/fastcgi_params '/usr/local/nginx/conf'
cp conf/fastcgi_params          '/usr/local/nginx/conf/fastcgi_params.default'
test -f '/usr/local/nginx/conf/fastcgi.conf'            || cp conf/fastcgi.conf '/usr/local/nginx/conf'
cp conf/fastcgi.conf '/usr/local/nginx/conf/fastcgi.conf.default'
test -f '/usr/local/nginx/conf/uwsgi_params'            || cp conf/uwsgi_params '/usr/local/nginx/conf'
cp conf/uwsgi_params            '/usr/local/nginx/conf/uwsgi_params.default'
test -f '/usr/local/nginx/conf/scgi_params'             || cp conf/scgi_params '/usr/local/nginx/conf'
cp conf/scgi_params             '/usr/local/nginx/conf/scgi_params.default'
test -f '/usr/local/nginx/conf/nginx.conf'              || cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf'
cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf.default'
test -d '/usr/local/nginx/logs'                 || mkdir -p '/usr/local/nginx/logs'
test -d '/usr/local/nginx/logs' ||              mkdir -p '/usr/local/nginx/logs'
test -d '/usr/local/nginx/html'                 || cp -R html '/usr/local/nginx'
test -d '/usr/local/nginx/logs' ||              mkdir -p '/usr/local/nginx/logs'
make[1]: Leaving directory `/home/dockerfile_nginx/nginx-1.9.9'

它创建了 /usr/local/nginx 目录,这个就是 nginx 的安装目录了,日志、启动文件都在这里。

4)启动并访问

1
2
3
4
5
6
7
[root@status sbin]# pwd
/usr/local/nginx/sbin
[root@status sbin]# ./nginx
[root@status sbin]# ps -ef | grep nginx
root     11694     1  0 15:53 ?        00:00:00 nginx: master process ./nginx
nobody   11695 11694  0 15:53 ?        00:00:00 nginx: worker process
root     11700  8800  0 15:53 pts/10   00:00:00 grep --color=auto nginx

根据操作步骤编写 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
# 基于anolisos
FROM registry.openanolis.cn/openanolis/anolisos:8

LABEL Author="test"
LABEL Remark="测试使用, 基于 anolisos 制作 Nginx 镜像"

# 解压包到工作目录
ADD nginx-1.25.1.tar.gz /usr/local

# 安装编译Nginx所需的依赖
RUN yum install -y gcc make openssl-devel pcre-devel zlib-devel

# 设置主目录
WORKDIR /usr/local/nginx-1.25.1

# 配置、编译和安装Nginx
RUN ./configure \
    --prefix=/usr/local/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-file-aio \
    --with-ipv6 \
    --with-http_v2_module \
    --with-cc-opt="-Wno-error" \
    && make \
    && make install


# 创建日志和缓存目录
RUN mkdir -p /var/log/nginx && \
    mkdir -p /var/cache/nginx

# 拷贝Nginx配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露80端口,供外部访问
EXPOSE 80

# 启动 nginx
CMD ["nginx", "-g", "daemon off;"]

nginx 配置

把 nginx.conf 文件放到 dockerfile 目录下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
user root; # 镜像里没有创建 nginx 用户,指定 root 用户来启动服务,不然会报错
worker_processes auto;
events {
  worker_connections 512;
  use epoll;
}
 
http {
  include mime.types;
  default_type application/octet-stream;
  access_log off;
  sendfile on;
  keepalive_timeout 75;
  server {
    listen 80;
    server_name 139.196.97.87;
    location / {
      proxy_pass http://139.196.97.87:8080;
    }
  }
}

构建镜像

1
2
3
4
5
6
7
8
[root@status dockerfile_nginx]# docker build -t nginx:v1 .

...
Step 11/11 : CMD nginx -g daemon off;
 ---> Running in 145e8f62d60c
 ---> dcfd18bb9209
Removing intermediate container 145e8f62d60c
Successfully built dcfd18bb9209

启动镜像

1
2
3
4
[root@status dockerfile_nginx]# docker run -d --name nginx -p 80:80 nginx:v1 
a4f70aab39a1665802135a47d7a5bc2edf6c15093e0fef27fa4db82d0690f917
[root@status dockerfile_nginx]# docker logs nginx 
nginx: [emerg] getpwnam("nginx") failed

这里报错了,没有找到 nginx 用户。

  • 1)在容器里创建一个 nginx 用户
  • 2)指定 root 用户为启动 Nginx 的用户

如果是使用 1 方案的话,应该得在 dockerfile 里 RUN 一条创建 nginx 用户的命令

1
useradd -r -s /sbin/nologin nginx

我使用了 2 方案,指定 root 用户启动。在 nginx.conf 添加一行

1
user root;

添加后重新构建镜像,然后启动。

1
2
3
4
5
6
7
8
[root@status dockerfile_nginx]# docker run -d --name nginx -p 80:80 nginx:v1 
ef443ef68ec75631a11ee52eeb2d8831610582a257154350cadb5af5ac72a97e
[root@status dockerfile_nginx]# docker logs nginx 
[root@status dockerfile_nginx]# docker ps
CONTAINER ID        IMAGE                                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
ef443ef68ec7        nginx:v1                                       "nginx -g 'daemon ..."   50 seconds ago      Up 48 seconds       0.0.0.0:80->80/tcp       nginx
d14c7820921d        test:v1                                        "/home/tomcat/apac..."   18 hours ago        Up 18 hours         0.0.0.0:8080->8080/tcp   test_tomcat
ae813af28fd9        registry.openanolis.cn/openanolis/anolisos:8   "/bin/bash"              24 hours ago        Up 24 hours                                  anolisos

一切正常,访问 IP:80 端口,成功跳转到 tomcat:8080 页面。

构建 Dockerfile 过程的问题

如何将本地的某个包放到容器内部?

需要将 rpm 包放到 centos 容器内

1.复制文件命令 cp

1
[root@status home]# docker container cp wget-1.14-18.el7_6.1.x86_64.rpm centos7:/home/
1
2
3
[root@9fb9bacc6189 home]# ll
total 548
-rw-r--r-- 1 root root 560272 Sep 13 07:45 wget-1.14-18.el7_6.1.x86_64.rpm

2.加载数据卷,但是容器内对数据卷里的内容做修改也会导致主机的内容被修改,这个不适用于现在的情况

3.构建 Docker 镜像时,使用 ADD 命令或者 COPY 命令,将文件添加进去

1
COPY /home/wget-1.14-18.el7_6.1.x86_64.rpm /home

如何将容器里打包好的文件传回主机?

  • 直接复制到主机
  • 挂载数据卷容器
  • 通过 docker 的管道 - 传回主机
复制

从容器复制到主机

1
2
3
4
[root@status dockerfile]# docker container cp anolisos:/home/jdk.tar.gz /home/dockerfile/
[root@status dockerfile]# ll
total 51100
-rw-r--r-- 1 root root 52325939 Sep 18 10:57 jdk.tar.gz

Network 实践

实践一:nginx 容器与 tomcat 容器互联

前提

从上边的实践一和实践二,可以成功的构建了 tomcat 镜像与 nginx 镜像

因为我的阿里云服务器网络策略,是把 tomcat 8080 端口和 nginx 80 端口都打开了,上边的两个镜像,成功的通过 nginx 跳转到 tomcat 页面。

[!IMPORTANT]

实际项目中,如果对外使用了 nginx 做反向代理或者负载均衡,则 tomcat(应用) 的 IP和端口是不对外开放的,统一通过 nginx 跳转应用。

所以我把阿里云服务器网络策略中 tomcat 8080 端口关掉,这样 tomcat 就无法访问,同时 nginx 就跳转不到 tomcat 上了。

[!IMPORTANT]

在主机 8080 端口关闭的前提下,为了能够让 nginx 成功跳转到 tomcat ,从容器内部出发。使用 docker 的 network 机制,将 nginx 容器和 tomcat 容器都加入到同一个网络中,让它们能够互相访问。

这样,外部只需要访问 nginx ,然后 nginx 通过 docker network 访问 tomcat 。

  • 这个实践是基于上边的实践一、实践二来操作的。

配置 network 容器互联

创建网络,将 nginx 和 tomcat 容器都拉进来

1
2
3
4
[root@status dockerfile_nginx]# docker network create ng_web_network
ddc7f8925ad5df07beabacb8c0f556f152fef9f937cf48c97fdd8078a3f49e14
[root@status dockerfile_nginx]# docker network connect ng_web_network nginx 
[root@status dockerfile_nginx]# docker network connect ng_web_network test_tomcat

查看网络详情,里边有两个容器了。

 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
[root@status dockerfile_nginx]# docker network inspect ng_web_network 
[
    {
        "Name": "ng_web_network",
        "Id": "ddc7f8925ad5df07beabacb8c0f556f152fef9f937cf48c97fdd8078a3f49e14",
        "Created": "2024-09-19T09:55:24.921745354+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "d14c7820921dd0150c1d4c9e9ff786164201f10f86c7dc63db6522ded8b2405a": {
                "Name": "test_tomcat",
                "EndpointID": "da006a7767d6937f310880a114c7d24a085c87573c84a9b47b91c99f79211473",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "ef443ef68ec75631a11ee52eeb2d8831610582a257154350cadb5af5ac72a97e": {
                "Name": "nginx",
                "EndpointID": "19569264099f4fdd3723309ff9512a2dbe9b6eea3b51e7318b2e8c1dba1a4074",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
nginx 跳转 tomcat 失败

[!IMPORTANT]

nginx 还是跳转不到 tomcat,问了 AI :

因为我在【dockerfile 实践一】里,对 tomcat 容器的端口进行映射,将 tomcat 8080 端口映射到了主机 8080 端口。不知道为啥不能这样,先试试。

所以我用镜像再生成一个没有映射端口的 tomcat 容器,看看效果。

1)重新执行镜像,并加入到 network 中

1
2
[root@status ~]# docker run -d --name tomcat --network ng_web_network test:v1 
fe5b1183ab41931e8e4c33c8c6cd4b03b4c098cd6212c91986a78b006c9a2533

2)把有端口映射的容器从这个 network 中移除

1
docker network disconnect ng_web_network test_tomcat

3)打开代理地址看看能否跳转

一般出现了连接超时,肯定是网络没通

查看网络,没反应,说明没通

1
[root@status ~]# docker exec -it nginx curl http://139.196.97.87:808
网络没通的原因

[!IMPORTANT]

Docker 网络内部使用 DNS 服务来解析容器名称到其 IP 地址的映射。

当在一个自定义网络中启动容器时,Docker 会为每个容器分配一个唯一的 IP 地址,并注册其容器名称到 Docker 内部 DNS 服务器。因此,在同一网络中的其他容器可以使用容器名称来访问它。

看一下这个 network 里边容器的 IP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[root@status ~]# docker network inspect ng_web_network
...
"Containers": {
            "ef443ef68ec75631a11ee52eeb2d8831610582a257154350cadb5af5ac72a97e": {
                "Name": "nginx",
                "EndpointID": "19569264099f4fdd3723309ff9512a2dbe9b6eea3b51e7318b2e8c1dba1a4074",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "fe5b1183ab41931e8e4c33c8c6cd4b03b4c098cd6212c91986a78b006c9a2533": {
                "Name": "tomcat",
                "EndpointID": "0c304895c8bdb0c149cb8ded2511d79d851be71059174e35551fbe80ce2e14e1",
                "MacAddress": "02:42:ac:13:00:04",
                "IPv4Address": "172.19.0.4/16",
                "IPv6Address": ""
            }
...

在【Dockerfile 实践 - 实践二 - 3 nginx 配置】中,配置的跳转的 IP 是我主机的 IP,而这个 tomcat 是运行在容器里的,实际的 tomcat 地址应该是 172.19.0.4:8080 ,我通过 nginx 的地址 139.196.97.87:80 跳转到 172.19.0.4:8080 才对。因为 docker network 是使用容器名来解析容器的 IP,所以这里我就需要跳转到 tomcat:8080

解决问题

好了,明白原因,改一下 nginx.conf 配置,然后更新到 nginx 容器内部 /etc/nginx/nginx.conf

1)nginx.conf 配置改为这样

1
2
3
4
5
6
server {
  listen 80;
  server_name 139.196.97.87;
  location / {
    proxy_pass http://tomcat:8080;
  }

2)使用 cp 命令传进去,然后重启 nginx 服务

1
2
3
4
# 传进去
docker container cp nginx.conf nginx:/etc/nginx/nginx.conf
# 重启
docker exec nginx nginx -s reload

nginx -s reload 是重启 nginx 命令

然后访问 139.196.97.87:80 ,成功跳转

总结

  • 应用如果是通过 nginx 跳转,则应用容器不需要映射端口
  • 应用通过 nginx 跳转,将应用和 nginx 容器都加入到同一个 network 中即可实现互相访问
  • 在同一个 network 中,使用容器名解析容器的IP,所以相关配置应该填写容器名

疑问

1.如果先映射了端口,后续想用 nginx 做代理的话,如何清除原来的端口映射?如果重新生成容器,原来的数据怎么办?

2.日志怎么处理?应用的日志、nginx 的日志怎么快速的查看?怎么做归集到专门的日志目录里?

Licensed under CC BY-NC-SA 4.0
最后更新于 2024年10月14号 22:37