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
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
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 的日志怎么快速的查看?怎么做归集到专门的日志目录里?