Docker 建站小记

楷哥 2021-01-24 11:14:03
docker 博客园 建站 技术开发 小记


一,前言

Docker 建站小记,我使用了四个镜像来搭建:nginx,certbot,mysql,gradle。欢迎访问:https://www.zzk0.top

这个网页是从 github 上找的个人主页,背景用的是 bing 的壁纸,中间有两个链接,一个指向我的 github,一个指向博客园。后端项目目前只有一个接口,当有人访问这个网站的时候,就会向后端项目发出一个请求,由 nginx 负责将对 api.zzk0.top 的请求转发到后端项目。

最理想的状态是,我直接 docker-compose up,我就可以将项目运行起来了。不过我的方法,需要自己手动配置一下才行,一个是初始化申请 SSL 的脚本,一个是定时分割 NGINX 日志。之后就只需要 docker-compose up 就行了。

这里简单讲讲这四个镜像分别是干什么的吧。

  • nginx,这个是 http 服务器,用来提供提供静态资源的,这篇博客大部分内容都是在讲如何配置 nginx。
  • certbot,这个用来申请 SSL 证书。设置了一个定时任务,每个月刷新一下证书。
  • mysql,后端项目数据库。
  • gradle,编译并运行 springboot 项目。

二,NGINX

重新加载配置

修改了 NGINX 的配置,但是又不想重新启动容器。我们可以通过向容器发送命令来加载新配置。

# docker exec -it your-name nginx -s reload
2021/01/23 02:30:58 [notice] 23#23: signal process started

HTTPS 配置

首先我们需要证书和密钥,我们可以使用免费的 Let's Encrypt 来生成,不过三个月就会过期,所以需要刷新一下。

证书的生成可以选择在本机上还是在 Docker 里,如果在本机上生成,我们可以选择 standalone 模式,但是这样的话,它需要短暂占用一下 80 端口来验证这个域名是否是你的。因此当你有一个正在运行的 NGINX 并且占用了 80 端口的话,我们需要去暂停它。如果在 Docker 中生成,并且你的网站有一个根目录,那么可以使用 webroot 模式,它会在你的网站根目录下生成一些文件,然后通过域名去访问它来验证这个域名是不是你的,使用 webroot 模式就不需要暂停 NGINX,因此对正在运行的网站影响会小一些。

选择前者的好处是,不需要定制 Docker,但是需要短暂停止服务器;选择后者的好处是,不需要停止服务器,可移植性更好一点,本机只需要有 Docker 就能跑,但是需要定制镜像比较麻烦。不过,这种比较常见的需求,我们上 docker hub 搜一搜,一找就有了:https://hub.docker.com/r/staticfloat/nginx-certbot/ 。再搜一搜,我们会发现另一个方案:为什么不搞一个 certbot 的容器呢?然后将 nginx 的容器和 certbot 的容器连接起来!好,那我们就加多一个容器,来帮我们生成 SSL 证书好了。

申请

这篇文章可以参考看看 certbot 的操作。这篇文章提供了 certbot 和 nginx 的方案。

从文章配套的 Github 仓库 中把它的脚本和配置文件复制粘贴过来,把所有的 example.org 域名改成自己的域名,然后运行它的脚本。如果失败了,建议检查一下是不是 NGINX 没有启动。这个脚本不会提醒你 NGINX 没有启动,如果失败了,很有可能是 NGINX 没有配置好。

一开始跑这个脚本,我失败了几次。之后逐步执行脚本,然后启动容器看看什么问题。一看,才知道原来是 https 的推荐参数文件没有下载好,所以手动下载了那几个文件,然后修改脚本为复制而不是下载。

重定向

nginx 将 http 重定向到 https,完整的配置文件可以看附录。

server {
listen 80;
server_name zzk0.top www.zzk0.top;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name zzk0.top www.zzk0.top;
root /var/www/html;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/zzk0.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zzk0.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
try_files $uri $uri/ =404;
}
}

配置子域名

假设有一个域名 test.com,我们需要将对 api.test.com 的请求转发到 Tomcat,对 test.com 的请求则直接提供静态网站。

这个需求比较简单,在 server 下面设置好 server_name 就可以了。另外,我们还需要注意不要让别人用 ip 访问我们的网站,网上的说法是,别人可以恶意使用未备案的域名指向这个 ip,然后导致网站被封掉了。

server {
listen 80 default_server;
server_name _;
return 403;
}
server {
listen 443 default_server;
server_name _;
ssl_certificate /etc/letsencrypt/live/zzk0.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zzk0.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 403;
}

访问日志

为了记录网站的访问记录,可以使用 NGINX 的访问日志来做记录,按天分割。NGINX 的镜像里面没有 crontab,所以这里就用主机来做。方法是每天定时将文件重命名,然后 reload NGINX。不过这个部分比较不智能,每次更换主机的时候,都需要手动去配置,还需要修改下面的路径。

#!/bin/sh
LOGS_PATH=/root/home/data/nginx
TODAY=$(date -d 'today' +%Y-%m-%d)
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error_${TODAY}.log
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${TODAY}.log
docker exec -i home-nginx nginx -s reload

接下来,将以下内容加入到 /etc/crontab 中,这样就可以执行每日任务了。每天凌晨4点的时候,自动分割日志。

0 4 * * * root /root/home/nginx/daily_log.sh >> /root/home/data/nginx/daily_log.log 2>&1

三,MySQL

有时候我们需要进入数据库的镜像里面去看看数据。

# 进入镜像
docker exec -it your-name bash
# 登录
mysql -uroot -p
# 罗列数据库
show database

四,后端项目

后端项目使用 SpringBoot 来做。需求是:启动 Docker 后构建源码并运行。这个部分使用 gradle 的镜像,启动的时候,运行 gradle bootRun 就可以了。

当我们更新了后端项目之后,我们只需要重启这个容器,就可以构建了。我的后端项目容器名字叫做 springboot,重启一下就可以将接口更新了,不过重启过程中的请求会失败。

docker restart springboot

下面是 docker-compose.yml 中的配置。

web:
container_name: springboot
restart: always
image: gradle:6.7.1-jdk8
depends_on:
- db
volumes:
- ./api:/home/gradle/project
environment:
TZ : 'Asia/Shanghai'
command: bash -c "cd /home/gradle/project && gradle bootRun"

附录

NGINX 配置

user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream tomcat {
server web:8080;
}
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;
limit_req_zone $binary_remote_addr zone=api_limit_req:10m rate=30r/m;
sendfile on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
# forbid access via ip address
server {
listen 80 default_server;
server_name _;
return 403;
}
server {
listen 443 default_server;
server_name _;
ssl_certificate /etc/letsencrypt/live/zzk0.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zzk0.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 403;
}
# configure zzk0.top, redirect to https and serve static files
server {
listen 80;
server_name zzk0.top www.zzk0.top;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name zzk0.top www.zzk0.top;
root /var/www/html;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/zzk0.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zzk0.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
try_files $uri $uri/ =404;
}
}
# configure api.zzk0.top, backend api
server {
listen 80;
server_name api.zzk0.top;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name api.zzk0.top;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/zzk0.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zzk0.top/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
limit_req zone=api_limit_req;
proxy_pass http://tomcat;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}

Docker 配置

version: '3'
services:
certbot:
container_name: home-certbot
restart: always
image: certbot/certbot
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 720h & wait $${!}; done;'"
nginx:
container_name: home-nginx
restart: always
image: nginx:1.18.0
ports:
- 80:80
- 443:443
depends_on:
- web
links:
- web:web
environment:
TZ : 'Asia/Shanghai'
volumes:
- ./html:/var/www/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
- ./data/nginx:/var/log/nginx
command: "/bin/sh -c 'while :; do sleep 720h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
db:
container_name: home-db
restart: always
image: mysql:8.0.13
ports:
- 7706:3306
volumes:
- ./data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: backend_database
MYSQL_USER: root
MYSQL_PASSWORD: root
web:
container_name: springboot
restart: always
image: gradle:6.7.1-jdk8
depends_on:
- db
volumes:
- ./api:/home/gradle/project
environment:
TZ : 'Asia/Shanghai'
command: bash -c "cd /home/gradle/project && gradle bootRun"
版权声明
本文为[楷哥]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/zzk0/p/14318711.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云