Docker Basics - 3

This article was last updated on: February 7, 2024 pm

Web servers and applications

Nginx

My Nginx Docker image

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
## 设置继承自己创建的 sshd 镜像 
FROM caseycui/ubuntu-sshd

## 维护者
LABEL maintainer="CaseyCui [email protected]"

## 安装 nginx
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
nginx \
geoip-bin \
fcgiwrap \
ssl-cert \
&& rm -rf /var/lib/apt/lists/* \
&& chown -R www-data:www-data /var/lib/nginx

## 添加脚本,并设置权限
COPY run-nginx.sh /run-nginx.sh
##RUN chmod 755 /run-nginx.sh

## 定义工作目录
WORKDIR /etc/nginx

## 添加挂载点 /var/www
VOLUME /var/www

## forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log

## 定义输出端口
EXPOSE 80
EXPOSE 443

## 定义输出命令
CMD ["/run-nginx.sh"]

run-nginx.sh Script:

1
2
## nginx 以 daemon off 形式启动 
/usr/sbin/nginx -g "daemon off;"

Why is it needed daemon off; ?

Imagine a scenario like this:

If there is no daemon off, nginx runs in the background, then nginx is not a pid 1 program, but executes other (such as bash), this bash executes nginx instructions and ends, and the container exits.

Or modify the /etc/nginx/nginx.conf file directly:

echo -e "\ndaemon off;" >> /etc/nginx/nginx.conf

Tomcat

Tomcat was originally developed by Sun’s software architect James Smith. Duncan. Davidson developed, later known as an open source project with his help, and contributed by Sun to the Apache Software Foundation.

Tomcat main function: Run JSP pages and servlets.

.JAVA

Enterprises typically use Sun JDK 6 or Oracle JDK 7+. The Dockerfile is as follows:

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
FROM caseycui/ubuntu-sshd

LABEL maintainer="CaseyCui [email protected]"

## 创建 /java 目录
RUN mkdir /java

## 解压 jdk 压缩包到 /java 目录
ADD jdk-7u80-linux-x64.tar.gz /java

## 1. 删除 src.zip,减少镜像 size
## ~~2. 配置 JAVA 环境变量~~
## ~~3. 使生效~~
## 下面为几种不同的 echo 写法(配置 ENV 则不需要手动在 /etc/profile 里添加)
## =======================================================
## echo -e "\nexport JAVA_HOME=/java/jdk1.7.0_80\nexport PATH=/java/jdk1.7.0_80/bin:$PATH\nexport CLASSPATH=.:/java/jdk1.7.0_80/lib/dt.jar:/java/jdk1.7.0_80/lib/tools.jar" >> /etc/profile
## =======================================================
## RUN { \
## echo; \
## echo 'export JAVA_HOME=/java/jdk1.7.0_80'; \
## echo 'export PATH=$JAVA_HOME/bin:$PATH'; \
## echo 'export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar'; \
## } >> /etc/profile \
## && source /etc/profile \
## && rm -f /java/jdk1.7.0_80/src.zip
## =======================================================

RUN rm -f /java/jdk1.7.0_80/src.zip

## 配置 ENV
## > The environment variables set using `ENV` will persist when a container is run from the resulting image.

ENV JAVA_HOME /java/jdk1.7.0_80
ENV JAVA_VERSION 7u80
ENV PATH $JAVA_HOME/bin:$PATH
ENV CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

Notes:

  • The JDK package is from the Oracle Support website.

  • THE JAVA ENVIRONMENT VARIABLE IS DIRECTLY IN ENV No need to manually write to /etc/profile

  • How do I write a multi-line string containing multiple special characters to a file? - with braces

Tomcat 8

The Dockerfile for Tomcat 8.0.X based on Oracle JDK 7 is as follows:

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
FROM caseycui/jdk7:7u80

LABEL maintainer='CaseyCui [email protected]'

ENV CATALINA_HOME /tomcat
ENV PATH $CATALINA_HOME/bin:$PATH

RUN mkdir -p "$CATALINA_HOME"

WORKDIR $CATALINA_HOME

## let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR

## runtime dependencies for Tomcat Native Libraries
## Tomcat Native 1.2+ requires a newer version of OpenSSL than debian:jessie has available
## > checking OpenSSL library version >= 1.0.2...
## > configure: error: Your version of OpenSSL is not compatible with this version of tcnative
## see http://tomcat.10.x6.nabble.com/VOTE-Release-Apache-Tomcat-8-0-32-tp5046007p5046024.html (and following discussion)
## and https://github.com/docker-library/tomcat/pull/31

ENV OPENSSL_VERSION 1.0.2g-1ubuntu4.8

## RUN set -ex; \
## if ! grep -q stretch /etc/apt/sources.list; then \
## # only add stretch if we're not already building from within stretch
## { \
## echo 'deb http://deb.debian.org/debian stretch main'; \
## } > /etc/apt/sources.list.d/stretch.list; \
## { \
## # add a negative "Pin-Priority" so that we never ever get packages from stretch unless we explicitly request them
## echo 'Package: *'; \
## echo 'Pin: release n=stretch'; \
## echo 'Pin-Priority: -10'; \
## echo; \
## # ... except OpenSSL, which is the reason we're here
## echo 'Package: openssl libssl*'; \
## echo "Pin: version $OPENSSL_VERSION"; \
## echo 'Pin-Priority: 990'; \
## } > /etc/apt/preferences.d/stretch-openssl; \
## fi

RUN apt-get update && apt-get install -y --no-install-recommends \
libapr1 \
openssl="$OPENSSL_VERSION" \
&& rm -rf /var/lib/apt/lists/*

## 安装跟 tomcat 用户认证相关的软件
RUN apt-get update && \
DIBIAN_FRONTEND=noninteractive \
apt-get install -yq --no-install-recommends \
wget \
pwgen \
ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

## see https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/KEYS
## see also "update.sh" (https://github.com/docker-library/tomcat/blob/master/update.sh)

ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 713DA88BE50911535FE716F5208B0AB1D63011C7 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23

RUN set -ex; \
for key in $GPG_KEYS; do \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done

## 设置 tomcat 的环境变量

ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.0.46
ENV TOMCAT_TGZ_URL http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz
ENV TOMCAT_ASC_URL https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc

## 复制 tomcat 到镜像中

RUN set -x \
\
&& wget -O tomcat.tar.gz "$TOMCAT_TGZ_URL" \
&& wget -O tomcat.tar.gz.asc "$TOMCAT_ASC_URL" \
&& gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz \
&& tar -xvf tomcat.tar.gz --strip-components=1 \
&& rm bin/*.bat \
&& rm tomcat.tar.gz* \
\
&& nativeBuildDir="$(mktemp -d)" \
&& tar -xvf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1 \
&& nativeBuildDeps=" \
dpkg-dev \
gcc \
libapr1-dev \
libssl-dev \
make \
" \
&& apt-get update && apt-get install -y --no-install-recommends $nativeBuildDeps && rm -rf /var/lib/apt/lists/* \
&& (\
export CATALINA_HOME="$PWD" \
&& cd "$nativeBuildDir/native" \
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
&& ./configure \
--build="$gnuArch" \
--libdir="$TOMCAT_NATIVE_LIBDIR" \
--prefix="$CATALINA_HOME" \
--with-apr="$(which apr-1-config)" \
--with-java-home="/java/jdk1.7.0_80" \
--with-ssl=yes \
&& make -j "$(nproc)" \
&& make install \
) \
&& apt-get purge -y --auto-remove $nativeBuildDeps \
&& rm -rf "$nativeBuildDir" \
&& rm bin/tomcat-native.tar.gz

## verify Tomcat Native is working properly
RUN set -e \
&& nativeLines="$(catalina.sh configtest 2>&1)" \
&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
&& nativeLines="$(echo "$nativeLines" | sort -u)" \
&& if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi

## 创建 tomcat 用户脚本
COPY create_tomcat_admin_user.sh /create_tomcat_admin_user.sh

## 创建 tomcat 运行脚本
COPY run-tomcat.sh /run-tomcat.sh

RUN chmod +x /*.sh && \
chmod +x /tomcat/bin/*.sh

## 挂载点
## 日志文件
VOLUME $CATALINA_HOME/logs

## 程序文件
VOLUME $CATALINA_HOME/webapps

EXPOSE 8080

CMD ["/run-tomcat.sh"]

Create a Tomcat user and password script file create_tomcat_admin_user.sh, which reads as follows:

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
##!/bin/bash

if [-f /.tomcat_admin_created]; then
echo "Tomcat 'admin' user already created"
exit 0
fi

## generate password
PASS=${TOMCAT_PASS:-$(pwgen -s 12 1)}
_word=$([ ${TOMCAT_PASS} ] && echo "preset" || echo "random")
echo "=> Creating and admin user with a ${_word} password in Tomcat"

##sed -i -r 's/<\/tomcat-user>//' ${CATALINA_HOME}/conf/tomcat-users.xml
## 这句的主要用法就是原本的 `tomcat-users.xml` 里存在一个空的 `<tomcat-users>` 到 `</tomcat-users>` 的字段,直接用 sed 删除最后一行,即 `</tomcat-users>`
## 然后补上我们生成的密码的相关内容,最后再加上 `</tomcat-users>`


sed -i '$d' ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-gui"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-script"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-jmx"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="admin-gui"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="admin-script"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo "<user username=\"admin\" password=\"${PASS}\" roles=\"manager-gui, manager-script, manager-jmx, admin-gui, admin-script\"/>" >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '</tomcat-users>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo "=> Done!"
touch /.tomcat_admin_created
echo "======================================================"
echo "You can now configure to this Tomcat server using:"
echo ""
echo " admin:${PASS}"
echo ""
echo "======================================================"

Tomcat startup script run-tomcat.sh:

1
2
3
4
5
6
7
##!/bin/bash

if [! -f /.tomcat_admin_created]; then
/create_tomcat_admin_user.sh
fi

exec ${CATALINA_HOME}/bin/catalina.sh run

The Tomcat cipher script is generated last tomcat-users.xml File:

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
<?xml version='1.0' encoding='utf-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">

<!--
NOTE: By default, no user is included in the "manager-gui" role required
to operate the "/manager/html" web application. If you wish to use this app,
you must define such a user - the username and password are arbitrary. It is
strongly recommended that you do NOT use one of the users in the commented out
section below since they are intended for use with the examples web
application.
-->

<!--
NOTE: The sample user and role entries below are intended for use with the
examples web application. They are wrapped in a comment and thus are ignored
when reading this file. If you wish to configure these users for use with the
examples web application, do not forget to remove the <!.. ..> that surrounds
them. You will also need to set the passwords to something appropriate.
-->

<!--
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
-->

<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="admin" password="vNc8guWjdrBP" roles="manager-gui, manager-script, manager-jmx, admin-gui, admin-script"/>
</tomcat-users>

Chapter Summary

Middleware serveris a best practice for Docker container apps for the following reasons:

  • Middleware servers are the main computing nodes in addition to the database server, which can easily become a performance bottleneck, so they usually need to be deployed in large batches, and Docker has many innate advantages for batch deployment
  • The middleware server structure is clear and stripped downConfiguration file log Code directory After that, containers can be in a state of almost zero growth, which makes the migration and batch deployment of containers more convenient.
  • Middleware server clustering is easy to implement after using F5 for hardware, Nginx for software, etc. for software for load balancing

When using middleware containers, You need to plan in advance for resources such as the purpose of the container and the network ports that may be open.

ForProgram code The resource directory of the program log Database file and other data that needs to be updated in real time must pass -v Parameters are mapped to the host’s directory, using Docker’s AUFS file format, which can cause big performance problems.

IBM Research test report on Docker’s various performance


Docker Basics - 3
https://e-whisper.com/posts/37110/
Author
east4ming
Posted on
September 27, 2021
Licensed under