念念不忘
必会回响

如何使用Docker Compose安装WordPress

最近把收藏多年的域名又续费了10年,如果不用的话又显得有些浪费,于是就打算在搞一个小网站打发打发时间,首先想起了马上要过期的SugarHosts,可惜发生了很多不愉快的事,导致我再也不会选择这个主机上。想起我还有一个闲置的RackNerd的VPS,所以就搜了下LNMP一键安装包,发现比较热门的都停止提供服务,只能自己安装,比起繁琐的安装步骤,我打算使用Docker来部署LNMP这一套服务,所有记此一文。

1.环境要求

  • 操作系统:我用的是debian11,或者Ubuntu 18.04以上即可
  • 安装好Docker、Docker Compose
  • 做好域名解析,确认@的A记录和WWW的A记录指向宿主机IP,并且DNS都已经更新(会出现你本地生效,但服务器没生效的情况,所以改完大约1-2小时应该就全部同步了)。
  • 本篇域名假设为 ABC.COM(顶级域名)

2.使用Docker Compose安装WordPress

2.1 先规整下目录

个人多年运维习惯,统一规整,比较直观的能找到你需要的路径。 目前我是将所有的配置文件、docker-compose.yml文件等统一放在/data/wordpress中。所以先创建/data/wordpress

mkdir -p /data/wordpress

在/data/wordpress中创建nginx配置文件

mkdir /data/wordpress/nginx-conf

2.2 创建nginx.conf

vim /data/wordpress/nginx-conf/nginx.conf

输入如下内容:

server {
        listen 80;
        listen [::]:80;

        server_name abc.com www.abc.com;

        index index.php index.html index.htm;

        root /var/www/html;

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass wordpress:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }
        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

2.3 定义环境变量

虽然是个个人网站,但也最好将一些敏感信息稍微的处理下。这里主要指的是数据库的认证信息。

在/data/wordpress目录中创建一个.env的文件

vim /data/wordpress/.env

定义如下三个变量

MYSQL_ROOT_PASSWORD=your_root_password
MYSQL_USER=your_wordpress_database_user
MYSQL_PASSWORD=your_wordpress_database_password

MYSQL_ROOT_PASSWORD指的是MySQL的root用户的密码。

MYSQL_USER 指的是MySQL的某个用户名,这个名字随意,例如wp_user

MYSQL_PASSWORD 指的是MYSQL_USER用户对应的密码

2.4 编写docker-compose文件

在这个文件中需要定义四个服务,分别是wordpress、mysql、nginx、cerbot(ssl证书签发),在/data/wordpress中创建docker-compose.yml文件,其完整内容如下:

version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes:
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

  wordpress:
    depends_on:
      - db
    image: wordpress:6.6.1-php8.3-fpm-alpine
    container_name: wordpress
    restart: unless-stopped
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - app-network

  webserver:
    depends_on:
      - wordpress
    image: nginx:1.27.1-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email your@email.com --agree-tos --staging -d abc.com -d www.abc.com

volumes:
  certbot-etc:
  wordpress:
  dbdata:

networks:
  app-network:
    driver: bridge

有对docker-compose不熟悉的可以去学习一下,上手还是非常快的。

2.5 获取SSL证书

在/data/wordpress中确认有docker-compose.yml文件,然后进入该目录,执行如下命令即可启动容器实例。

cd /data/wordpress
docker-compose up -d

此时,控制台会打印如下内容:

WARN[0000] /data/wordpress/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 6/6
✔ Network wordpress_default      Created                                                                                                                                                                 0.1s 
 ✔ Network wordpress_app-network  Created                                                                                                                                                                 0.1s 
 ✔ Container db                   Started                                                                                                                                                                 0.7s 
 ✔ Container wordpress            Started                                                                                                                                                                 1.4s 
 ✔ Container webserver            Started                                                                                                                                                                 2.1s 
 ✔ Container certbot              Started

如此即表示容器实例都启动成功,这里面只有certbot这个实例会出现问题,主要就是DNS解析的问题,所以在第一章就要求了提前确认DNS的解析是正确的。由于certbot执行完就会退出,所以我们可以通过查看日志来确认该实例执行成功

docker-compose logs certbot

如果执行成功的话会打印如下内容:

WARN[0000] /data/wordpress/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
certbot  | Saving debug log to /var/log/letsencrypt/letsencrypt.log
certbot  | Requesting a certificate for abc.com www.abc.com
certbot  | 
certbot  | Successfully received certificate.
certbot  | Certificate is saved at: /etc/letsencrypt/live/abc.com/fullchain.pem
certbot  | Key is saved at:         /etc/letsencrypt/live/abc.com/privkey.pem
certbot  | This certificate expires on 2024-11-20.
certbot  | These files will be updated when the certificate renews.
certbot  | NEXT STEPS:
certbot  | - The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

举一反三,如果要查看 mysql、nginx等服务器,只需要将cerbot修改为对应的容器名称

docker-compose logs service_name

虽然日志提示执行成功,但还需要再次验证是否挂载到webserver容器中了

docker-compose exec webserver ls -la /etc/letsencrypt/live

如果可以看到证书文件就说明执行成功了。此时,将docker-compose.yml中的certbot服务的command修改一下,打开docker-compose.yml

vim /data/wordpress/docker-compose.yml

找到certbot,修改为如下内容(只需要修改command的值即可):

...
  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email your@email.com --agree-tos --no-eff-email --force-renewal -d abc.com -d www.abc.com
...

修改完成后,重新创建certbot

docker-compose up --force-recreate --no-deps certbot

这个命令执行成功会打印如下内容:

WARN[0000] /data/wordpress/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 1/1
 ✔ Container certbot  Recreated                                                                                                                                                                           0.1s 
Attaching to certbot
certbot  | Saving debug log to /var/log/letsencrypt/letsencrypt.log
certbot  | Account registered.
certbot  | Renewing an existing certificate for abc.com
certbot  | 
certbot  | Successfully received certificate.
certbot  | Certificate is saved at: /etc/letsencrypt/live/abc.com/fullchain.pem
certbot  | Key is saved at:         /etc/letsencrypt/live/abc.com/privkey.pem
certbot  | This certificate expires on 2024-11-20.
certbot  | These files will be updated when the certificate renews.
certbot  | NEXT STEPS:
certbot  | - The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.
certbot  | 
certbot  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot  | If you like Certbot, please consider supporting our work by:
certbot  |  * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
certbot  |  * Donating to EFF:                    https://eff.org/donate-le
certbot  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot exited with code 0

2.6 修改nginx的配置文件,使其支持ssl

在 Nginx 配置中启用 SSL 将涉及添加到 HTTPS 的 HTTP 重定向、指定 SSL 证书和密钥位置,以及添加安全参数和标头。因为要修改配置文件,所以先停止webserver

docker-compose stop webserver

获取一份ssl-nginx.conf的模板,可以在/data/wordpress目录中执行如下命令获取:

curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf

打开/data/wordpress/nginx-conf/nginx.conf配置文件,删除所有内容。

vim /data/wordpress/nginx-conf/nginx.conf

删除所有内容后,将如下内容拷贝进去

server {
        listen 80;
        listen [::]:80;

        server_name abc.com www.abc.com;

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

        location / {
                rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name abc.com www.abc.com;

        index index.php index.html index.htm;

        root /var/www/html;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/abc.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/abc.com/privkey.pem;

        include /etc/nginx/conf.d/options-ssl-nginx.conf;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass wordpress:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }
        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

注意,将abc.com替换为你自己的域名。修改完配置文件后,再打开docker-compose.yml文件,添加443端口映射

vim /data/wordpress/docker-compose.yml

找到webserver,将posts修改为如下:

...
  webserver:
    depends_on:
      - wordpress
    image: nginx:1.27.1-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

保存即可,下面贴一份最终完全版的docker-compose.yml内容

version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes:
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

  wordpress:
    depends_on:
      - db
    image: wordpress:6.6.1-php8.3-fpm-alpine
    container_name: wordpress
    restart: unless-stopped
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - app-network

  webserver:
    depends_on:
      - wordpress
    image: nginx:1.27.1-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes: 
      - certbot-etc:/etc/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email iat@outlook.com --agree-tos --no-eff-email --force-renewal -d abc.com -d www.abc.com

volumes:
  certbot-etc: 
  wordpress:
  dbdata:

networks:
  app-network:
    driver: bridge

然后重新创建webserver

docker-compose up -d --force-recreate --no-deps webserver

查看容器实例进程

docker-compose ps
WARN[0000] /data/wordpress/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
NAME        IMAGE                               COMMAND                  SERVICE     CREATED       STATUS       PORTS
db          mysql:8.0                           "docker-entrypoint.s…"   db          5 hours ago   Up 5 hours   3306/tcp, 33060/tcp
webserver   nginx:1.27.1-alpine                 "/docker-entrypoint.…"   webserver   5 hours ago   Up 5 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp
wordpress   wordpress:6.6.1-php8.3-fpm-alpine   "docker-entrypoint.s…"   wordpress   5 hours ago   Up 5 hours   9000/tcp

确认都运行正常,打开https://abc.com,根据提示安装WordPress即可。

当然,可能会有人有疑问,如果重启会不会数据就没了,其实数据都映射到宿主机了,在docker-compose.yml中,有个volumes定义了三个卷,分别是certbot-etc、wordpress、dbdata,可执行如下命令查看

 docker volume ls |grep wordpress
local     wordpress_certbot-etc
local     wordpress_dbdata
local     wordpress_wordpress

查看wordpress的实际路径

docker volume inspect wordpress_wordpress
[
    {
        "CreatedAt": "2024-08-21T22:10:09-04:00",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "wordpress",
            "com.docker.compose.version": "2.29.2",
            "com.docker.compose.volume": "wordpress"
        },
        "Mountpoint": "/var/lib/docker/volumes/wordpress_wordpress/_data",
        "Name": "wordpress_wordpress",
        "Options": null,
        "Scope": "local"
    }
]

在宿主机的/var/lib/docker/volumes/wordpress_wordpress/_data目录就是容器中wordpress的路径

ls /var/lib/docker/volumes/wordpress_wordpress/_data
index.php    readme.html      wp-admin            wp-comments-post.php  wp-config.php         wp-content   wp-includes        wp-load.php   wp-mail.php      wp-signup.php     xmlrpc.php
license.txt  wp-activate.php  wp-blog-header.php  wp-config-docker.php  wp-config-sample.php  wp-cron.php  wp-links-opml.php  wp-login.php  wp-settings.php  wp-trackback.php

不过,为了避免不必要的损失,建议还是在wordpress中安装备份插件,定期备份数据。

2.7 续签证书

Let’s Encrypt 证书的有效期为 90 天,所以需要每三个月重新续签一份证书,方法如下:

创建一个续签的脚本 ssl_renew.sh

vim ~/ssl_renew.sh

将如下代码添加到该文件中

#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"

cd /data/wordpress/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

注意检查路径,然后添加到corntab中

0 1 1 * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1

每月1日的凌晨1点执行。

3. 注意事项

  • 注意将所有的abc.com替换为你自己的域名
  • 严格按照顺序执行
  • 对nginx配置文件、docker-compose文件有不懂的,建议简单学习一下。
赞(0) 打赏
未经允许不得转载:堆上小栈 » 如何使用Docker Compose安装WordPress

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册