#### **项目目录结构**
```bash
competitionShare
|-- docker-compose.yml #docker-compose编排文件
|-- fastdfs #fastdfs文件服务器目录
| |-- build #编译目录
| | `-- Dockerfile #编译文件
| |-- data #数据存放目录
| | |-- storage #文件数据存储目录
| | | |-- data
| | | `-- logs
| | `-- tracker #tracker日志和元数据目录
| | |-- data
| | `-- logs
| `-- nginx
| `-- logs
|-- mysql
| |-- conf
| | `-- mysqld.cnf #mysql配置文件
| |-- data #mysql数据存放目录
| |-- db_init_sql
| | `-- competitionShare.sql #项目的表结构和初始化数据sql
| `-- log
|-- nginx
| |-- conf
| | |-- mysite.template #nginx模板文件
| | `-- nginx.conf #nginx配置文件
| |-- html
| | `-- competitionShare_web #项目静态站点目录
| | |-- index.html
| | `-- static
| |-- log
| `-- ssl #ssl证书目录
| |-- demo.xxxxx.org.cn
| | |-- fullchain.pem
| | `-- privkey.pem
| `-- fastdfs.xxxxx.org.cn
| |-- fullchain.pem
| `-- privkey.pem
`-- tomcat #tomcat目录
|-- conf
| `-- server.xml #tomcat的server.xml文件
|-- log
`-- webapps
|-- competitionShare #项目API接口
`-- competitionShareBackstage #项目后台
```
#### **创建fastdfs容器使用的目录**
```bash
$ mkdir fastdfs/{build,data,nginx} -p
```
build:存放fastdfs构建目录
data:存放fastdfs数据的目录
nginx:存放nginx日志
#### **创建fastdfs/build/Dockerfile**
```bash
FROM alpine:3.6
MAINTAINER ynotes <admin@ynotes.cn>
#编译参数
ARG HOME=/root
ARG FASTDFS_VERSION=5.11
ARG LIBFASTCOMMON_VERSION=1.0.38
ARG FASTDFS_NGINX_MODULE_VERSION=1.20
ARG NGINX_VERSION=1.12.1
ARG FDFS_NGX_PORT #添加FDFS_NGX_PORT参数
ARG TRACKER_PORT
#环境变量
ENV FDFS_NGX_PORT "$FDFS_NGX_PORT" #读取docker-compose的变量FDFS_NGX_PORT
ENV TRACKER_PORT "$TRACKER_PORT" #读取docker-compose的变量TRACKER_PORT
#下载包
RUN cd ${HOME} \
&& sed -i 's#http://[^/]*/\(.*\)$#http://mirrors.aliyun.com/\1#g' /etc/apk/repositories \
&& apk update \
&& apk add --no-cache --virtual .build-deps bash gcc libc-dev make openssl-dev pcre-dev zlib-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev \
&& curl -fLS https://github.com/happyfish100/fastdfs/archive/V${FASTDFS_VERSION}.tar.gz -o V${FASTDFS_VERSION}.tar.gz \
&& curl -fLS https://github.com/happyfish100/libfastcommon/archive/V${LIBFASTCOMMON_VERSION}.tar.gz -o V${LIBFASTCOMMON_VERSION}.tar.gz \
&& curl -fLS https://github.com/happyfish100/fastdfs-nginx-module/archive/V${FASTDFS_NGINX_MODULE_VERSION}.tar.gz -o V${FASTDFS_NGINX_MODULE_VERSION}.tar.gz \
&& curl -fSL http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o nginx-${NGINX_VERSION}.tar.gz \
&& tar xf V${FASTDFS_VERSION}.tar.gz \
&& tar xf V${LIBFASTCOMMON_VERSION}.tar.gz \
&& tar xf V${FASTDFS_NGINX_MODULE_VERSION}.tar.gz \
&& tar zxf nginx-${NGINX_VERSION}.tar.gz
#安装包
RUN cd ${HOME}/libfastcommon-${LIBFASTCOMMON_VERSION}/ \
&& ./make.sh \
&& ./make.sh install \
&& cd ${HOME}/fastdfs-${FASTDFS_VERSION}/ \
&& ./make.sh \
&& ./make.sh install \
&& sed "s@/home/yuqing/fastdfs@/data/fastdfs/tracker@g" /etc/fdfs/tracker.conf.sample > /etc/fdfs/tracker.conf \
&& sed "s@/home/yuqing/fastdfs@/data/fastdfs/storage@g" /etc/fdfs/storage.conf.sample > /etc/fdfs/storage.conf \
&& sed "s@/home/yuqing/fastdfs@/data/fastdfs/storage@g" /etc/fdfs/client.conf.sample > /etc/fdfs/client.conf \
&& sed -i 's#CORE_INCS=.*#CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"#g' ${HOME}/fastdfs-nginx-module-${FASTDFS_NGINX_MODULE_VERSION}/src/config \
&& sed -i 's#ngx_module_incs=.*#ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/"#g' ${HOME}/fastdfs-nginx-module-${FASTDFS_NGINX_MODULE_VERSION}/src/config \
&& chmod u+x ${HOME}/fastdfs-nginx-module-${FASTDFS_NGINX_MODULE_VERSION}/src/config \
&& cd ${HOME}/nginx-${NGINX_VERSION} \
&& ./configure --add-module=${HOME}/fastdfs-nginx-module-${FASTDFS_NGINX_MODULE_VERSION}/src \
&& make && make install
#配置包
RUN cp ${HOME}/fastdfs-nginx-module-${FASTDFS_NGINX_MODULE_VERSION}/src/mod_fastdfs.conf /etc/fdfs/ \
&& sed -i "s#^store_path0.*#store_path0 = /data/fastdfs/storage#g" /etc/fdfs/mod_fastdfs.conf \
&& sed -i "s#^url_have_group_name.*#url_have_group_name = true#g" /etc/fdfs/mod_fastdfs.conf \
&& cd ${HOME}/fastdfs-${FASTDFS_VERSION}/conf/ \
&& cp http.conf mime.types /etc/fdfs/ \
&& echo -e "worker_processes 2;\nevents { \nworker_connections 10240; \n}\nhttp { \ninclude mime.types;\ndefault_type application/octet-stream;\nsendfile on;\nkeepalive_timeout 65;\nserver {\nlisten $FDFS_NGX_PORT;\nserver_name localhost;\nlocation ~/group([0-9])/M00 {\nngx_fastdfs_module;\n}\n}\n}">/usr/local/nginx/conf/nginx.conf
#清理包
RUN rm -rf ${HOME}/* \
&& apk del .build-deps gcc libc-dev make openssl-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev \
&& apk add bash pcre-dev zlib-dev
#安装脚本
RUN echo -e "mkdir -p /data/fastdfs/storage/data\nmkdir -p /data/fastdfs/tracker\nln -s /data/fastdfs/storage/data /data/fastdfs/storage/data/M00\nsed -i "s/^tracker_server=.*$/tracker_server=\$HOST_IP:$TRACKER_PORT/g" /etc/fdfs/storage.conf\nsed -i "s/^tracker_server=.*$/tracker_server=\$HOST_IP:$TRACKER_PORT/g" /etc/fdfs/mod_fastdfs.conf\n/etc/init.d/fdfs_trackerd start \n/etc/init.d/fdfs_storaged start\n/usr/local/nginx/sbin/nginx\ntail -f /usr/local/nginx/logs/access.log" >/start.sh \
&& chmod +x /start.sh
ENTRYPOINT ["/bin/bash","/start.sh"]
```
#### **创建mysql容器使用的目录**
```bash
$ mkdir mysql/{conf,data,db_init_sql,log} -p
$ chmod 777 mysql/log
```
conf:存放mysql配置文件
data:存放mysql数据的目录
log:存放mysql日志,修改权限为777
#### **编辑mysql配置文件mysql/conf/mysqld.cnf**
```bash
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
default-time-zone = '+08:00'
character-set-server=utf8
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character-set-client-handshake = FALSE
innodb_buffer_pool_size = 128M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
```
#### **创建nginx容器使用的目录**
```bash
$ mkdir nginx/{conf,html,log,ssl}
$ mkdir nginx/ssl/{demo.xxxxx.org.cn,fastdfs.xxxxx.org.cn}
$ chmod 777 nginx/log
```
conf:存放nginx的配置文件
html: 静态站点存放目录
log:存放日志目录
ssl: ssl证书存放目录
#### **编辑nginx/conf/nginx.conf**
```nginx
user nginx;
worker_processes 2;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 10240;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/demo.xxxxx.org.cn.conf;
}
```
#### **编辑nginx/conf/mysite.template**
```nginx
upstream my_tomcat{
server $TOMCAT:8080;
}
upstream my_fdfs{
server $FASTDFS:8888;
}
server {
listen $NGINX_PORT;
server_name $NGINX_HOST;
charset utf-8;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen $NGINX_SSL_PORT ssl http2;
server_name $NGINX_FASTDFS_HOST;
add_header X-Frame-Options SAMEORIGIN;
access_log /var/log/nginx/fastdfs.xxxxx.org.cn.access.log main;
location ~ .*.(svn|Git|cvs) {
deny all;
}
ssl_certificate "/etc/nginx/ssl/fastdfs.xxxxx.org.cn/fullchain.pem";
ssl_certificate_key "/etc/nginx/ssl/fastdfs.xxxxx.org.cn/privkey.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location ~ /group1/M00 {
add_header Strict-Transport-Security max-age=86400;
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://my_fdfs;
}
}
server {
listen $NGINX_SSL_PORT ssl http2 default_server;
server_name $NGINX_HOST;
add_header X-Frame-Options SAMEORIGIN;
access_log /var/log/nginx/demo.xxxxx.org.cn.access.log main;
location ~ .*.(svn|Git|cvs) {
deny all;
}
location / {
add_header Strict-Transport-Security max-age=86400;
root /var/www/html/competitionShare_web;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
ssl_certificate "/etc/nginx/ssl/demo.xxxxx.org.cn/fullchain.pem";
ssl_certificate_key "/etc/nginx/ssl/demo.xxxxx.org.cn/privkey.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
# Finally, send all non-media requests to the Django server.
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location /competitionShare {
add_header Strict-Transport-Security max-age=86400;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_pass http://my_tomcat;
}
location ^~ /competitionShareBackstage {
add_header Strict-Transport-Security max-age=86400;
proxy_set_header Host $host:$server_port;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_pass http://my_tomcat;
}
}
```
#### **拷贝SSL证书到对应的nginx/ssl/{demo.xxxxx.org.cn,fastdfs.xxxxx.org.cn}目录**
```bash
$ scp fullchain.pem root@docker-host:/root/docker_compose_demo/competitionShare/nginx/ssl/demo.xxxxx.org.cn
$ scp privkey.pem root@docker-host:/root/docker_compose_demo/competitionShare/nginx/ssl/demo.xxxxx.org.cn
$ scp fullchain.pem root@docker-host:/root/docker_compose_demo/competitionShare/nginx/ssl/fastdfs.xxxxx.org.cn
$ scp privkey.pem root@docker-host:/root/docker_compose_demo/competitionShare/nginx/ssl/fastdfs.xxxxx.org.cn
```
#### **创建tomcat容器使用的目录**
```bash
$ mkdir tomcat/{conf,log,webapps}
```
conf:tomcat配置存放目录
log:存放日志目录
webapps: 项目存放目录
#### **编辑tomcat/conf/server.xml**
```xml
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
```
#### **拷贝项目到tomcat/webapps目录**
```bash
$ scp competitionShare root@docker-host:/root/docker_compose_demo/competitionShare/tomcat/webapps
$ scp competitionShareBackstage root@docker-host:/root/docker_compose_demo/competitionShare/tomcat/webapps
```
#### **替换tomcat项目中mysql和fastdfs配置**
数据库配置
```bash
env=${PROJECT_ENV}
demo.jdbc_url=${DEMO_JDBC_URL}
demo.jdbc_username=${DEMO_JDBC_USER}
demo.jdbc_password=${DEMO_JDBC_PASS}
```
fastdfs配置
```bash
tracker_server = fastdfs:22122
```
#### **编辑docker-compose.yml**
```xml
version: '3'
services:
db:
image: mysql:5.7
restart: always
container_name: cs_web-db
environment:
MYSQL_ROOT_PASSWORD: abc123456
MYSQL_DATABASE: competitionShare
MYSQL_USER: demo
MYSQL_PASSWORD: abc123456
volumes:
- ./mysql/conf/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
- ./mysql/db_init_sql:/docker-entrypoint-initdb.d
- ./mysql/data:/var/lib/mysql
- ./mysql/log:/var/log
fastdfs:
build:
context: ./fastdfs/build/
dockerfile: Dockerfile
args:
TRACKER_PORT: 22122
FDFS_NGX_PORT: 8888
image: fastdfs-nginx:5.11
restart: always
container_name: cs_web-fastdfs
environment:
TRACKER_PORT: 22122
FDFS_NGX_PORT: 8888
HOST_IP: fastdfs
volumes:
- ./fastdfs/data:/data/fastdfs
- ./fastdfs/nginx/logs:/usr/local/nginx/logs/
nginx:
image: nginx:stable
restart: always
container_name: cs_web-nginx
environment:
NGINX_HOST: demo.xxxxx.org.cn
NGINX_FASTDFS_HOST: fastdfs.xxxxx.org.cn
NGINX_PORT: 80
NGINX_SSL_PORT: 443
TOMCAT: cs_web-tomcat
FASTDFS: cs_web-fastdfs
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf/mysite.template:/etc/nginx/conf.d/mysite.template
- ./nginx/ssl/demo.xxxxx.org.cn/fullchain.pem:/etc/nginx/ssl/demo.xxxxx.org.cn/fullchain.pem
- ./nginx/ssl/demo.xxxxx.org.cn/privkey.pem:/etc/nginx/ssl/demo.xxxxx.org.cn/privkey.pem
- ./nginx/ssl/fastdfs.xxxxx.org.cn/fullchain.pem:/etc/nginx/ssl/fastdfs.xxxxx.org.cn/fullchain.pem
- ./nginx/ssl/fastdfs.xxxxx.org.cn/privkey.pem:/etc/nginx/ssl/fastdfs.xxxxx.org.cn/privkey.pem
- ./nginx/log/:/var/log/nginx/
- ./nginx/html/competitionShare_web/:/var/www/html/competitionShare_web/
command: /bin/bash -c "envsubst '$$NGINX_HOST $$NGINX_PORT $$NGINX_SSL_PORT $$TOMCAT $$FASTDFS $$NGINX_FASTDFS_HOST' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/demo.xxxxx.org.cn.conf && nginx -g 'daemon off;'"
tomcat:
image: tomcat:8.0.53-jre8
restart: always
depends_on:
- db
- fastdfs
container_name: cs_web-tomcat
environment:
PROJECT_ENV: demo
JAVA_OPTS: "-Dsupplements.host=supplements"
CATALINA_OPTS: "-server -Xms256M -Xmx1024M -XX:MaxNewSize=256m"
DEMO_JDBC_URL: jdbc:mysql://db:3306/competitionShare??characterEncoding=UTF-8
DEMO_JDBC_USER: demo
DEMO_JDBC_PASS: abc123456
FDFS_URL: https://fastdfs.demo.org.cn/
volumes:
- ./tomcat/webapps:/usr/local/tomcat/webapps
- ./tomcat/conf/server.xml:/usr/local/tomcat/conf/server.xml
- ./tomcat/log:/log
```
#### **启动**
```bash
$ docker-compose up
```

#### **浏览器访问**
