目錄

SSL Nginx Docker ~ WordPress大搬家最終章

SSL 與 Nginx 以及Docker大集合囉

這是第三篇,我會先從如何將舊站搬家到新站開始講解,如果沒有這個需求的人,可以直接跳到 SSL 、docker與certbot這個章節開始看喔。

舊站備份

首先我們要搬家,有哪些東西是新的網站沒有的?文章跟WP的外掛與佈景主題,這些是不會在新的Wordpress上有的,因此我們要帶走的就是這些東西。

1
sudo tar zcvf backup.tar.gz /your/wordpress/path/wp-content

先把你舊的wordpress資料夾下的wp-content給壓縮打包

然後把它傳到新的主機上頭,接著再把它解壓縮,之後取代掉新站上的wp-content,步驟如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sudo tar zxvf backup.tar.gz
sudo mv ~/docker-wordpress/wordpress/wp-content ~/docker-wordpress/wordpress/wp-content_old
//請按照自己設定的docker-wordpress去改路徑。

sudo mv wp-content ~/docker-wordpress/wordpress/wp-content

//因為我們是用sudo去解壓縮的,會有權限問題,請按照以下步驟執行
cd ~/docker-wordpress/wordpress/
sudo chown -R www-data:www-data wp-content
//這個步驟就是將wp-content的所有權改成www-data

wp-content這樣就算還原完成了,這時候你打開你的新站,你會發現還是沒有什麼變化,那是因為我們的SQL還沒有匯入,因此我們要先把舊站的SQL匯出來。

1
2
3
4
5
6
7
8
9
mysqldump -uDB使用者 -p'DB密碼' DB名稱 > backup.sql

//這樣就匯出來了,接著把它壓縮起來 
tar zcvf sql.tar.gz backup.sql

//然後搬到新主機上,解壓縮,並且匯入它
tar zxvf sql.tar.gz
docker exec -i wordpress-docker_db_1 /usr/bin/mysql -uDB使用者 -p'DB密碼' DB名稱 &< backup.sql
//這樣就完成了,這裡的DB使用者跟密碼還有名稱,就看docker-compose.yml裡面設定的。

這時候你打開看你的網站,你會發現,天啊這是什麼情況,怎麼會破圖,甚至無法打開呢?那是因為SQL上的網址設定是舊的(或者你沒有改網址,但是之前是https,現在還是http),這時候我們可以參考[官方文件][15],然後使用以下方法:
我們先用phpmyadmin去修改舊站上的SQL,然後匯出來,在匯入就行了。[參考這個][16],然後請注意我們還是在用http喔,記得不要打成https了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
UPDATE wp_options
SET option_value = REPLACE(option_value, '舊網址', '新網址')
-- 僅替換與網站相關的條件
WHERE option_name = 'home' OR option_name = 'siteurl';

UPDATE wp_postmeta
SET meta_value = REPLACE(meta_value, '舊網址', '新網址');

UPDATE wp_posts
SET post_content = REPLACE(post_content, '舊網址', '新網址');

UPDATE wp_posts
SET guid = REPLACE(guid, '舊網址', '新網址');

SSL 配置

接下來就是我們要讓nginx與certbot還有dokcer一起合作,讓我們的網站更安全了,首先我們先來安裝下certbot,這個可以頒發免費的證書給你的域名,雖然短短的只有三個月,但是時間到了就更新一下,甚至可以自動化,不用白不用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

//這樣就安裝起來了</code></pre>

# 接著我們來擴展一下我們的image。

cd ~
mkdir wordpress-docker-image
cd wordpress-docker-image
touch Dockerfile

這個image需要自發的證書才能運行,我們還要另外裝一個ssl-cert。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apt-get -y install ssl-cert
make-ssl-cert generate-default-snakeoil

//然後複製到當前的目錄wordpress-docker-image
cp -p /etc/ssl/certs/ssl-cert-snakeoil.pem .
cp -p /etc/ssl/private/ssl-cert-snakeoil.key .

//在這個目錄下我們會看到下面三個文件
root@vps:~/wordpress-docker-image# ll
total 20
drwxr-xr-x  2 root root     4096 Jan 19 09:42 ./
drwx------ 11 root root     4096 Jan 20 16:20 ../
-rw-r--r--  1 root root      264 Jan 19 09:42 Dockerfile
-rw-r-----  1 root ssl-cert 1704 Jan 19 09:41 ssl-cert-snakeoil.key
-rw-r--r--  1 root root     1066 Jan 19 09:41 ssl-cert-snakeoil.pem

接下來我們來寫Dockerfile。nano Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# The base image
FROM wordpress:apache

# Enabling the SSL module
RUN a2enmod ssl

# Copy the SSL certs to the image
RUN mkdir /etc/apache2/certs
COPY ssl-cert-snakeoil.pem /etc/apache2/certs/ssl-cert.pem
COPY ssl-cert-snakeoil.key /etc/apache2/certs/ssl-cert.key

然後我們就來build這個image,這裡我示範的名稱是ssl-wordpress,你可以修改成任何的。

1
docker build -t ssl-wordpress:latest .

接著我們要來添加一下文件,讓我們的wordpress可以用SSL。
先到~/wordpress-docker/ 目錄底下。我們要創建一個資料夾跟一個文件。

1
2
3
cd ~/wordpress-docker
mkdir apache
nano apache/site.conf

接著我們要來寫一下 site.conf

 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
<VirtualHost *:80>
    #ServerName www.example.com
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
       #ServerName www.example.com
        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on
        SSLCertificateFile      /etc/apache2/certs/ssl-cert.pem
        SSLCertificateKeyFile   /etc/apache2/certs/ssl-cert.key

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
            SSLOptions +StdEnvVars
        </Directory>
    </VirtualHost>
</IfModule>

好的,我們來改一下docker-compose.yml囉。我們之前是用20851來映射80,現在我們用20435來映射443,而前面的數字都可以更改的,我們可以用208XX來管理映射80/8080,204XX來管理映射443。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
...
...
wordpress:
  depends_on:
    - db
    - redis
  image: ssl-wordpress:latest
  volumes:
    - ./wordpress:/var/www/html
    - ./apache/site.conf:/etc/apache2/sites-enabled/000-default.conf
  ports:
    - "20851:80"
    - "20435:443"
  restart: always
...
...

接著重新的啟動容器並且驗證一下是否可以使用https了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
docker-compose down && docker-compose up -d
curl -k --head https://localhost:20435

//你會看到以下內容

root@vps:~/wordpress-docker-image# curl -k --head https://localhost:20435
HTTP/1.1 301 Moved Permanently
Date: Wed, 20 Jan 2021 09:18:41 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/7.4.14
X-Redirect-By: WordPress
Location: https://localhost/
Content-Type: text/html; charset=UTF-8

剩下兩個步驟了,就快完成囉,接下來我們要讓nginx反向代理我們的ssl-wordpress。

1
2
3
4
sudo nano /etc/nginx/conf.d/example.com.conf

在裡面把20851的那條註解掉,並且新增一條
proxy_pass https://localhost:20435;

看起來會像這樣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server {
    listen 80;

    server_name example.com;

    location / {
        #proxy_pass http://localhost:20851;
        proxy_pass https://localhost:20435;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

然後我們先重新讀取我們的nginx讓改動生效後,在使用certbot來獲得證書。

1
2
3
4
5
6
7
sudo nginx -t
//先檢查有沒有問題
sudo nginx -s reload

//接著來獲得證書
certbot --nginx
//接著會要你填email阿,還有一些選項,就看自己的需求囉。

到這邊,大致上一個docekr wordpress就完成囉。最後我會說明一個跳轉網址的方法,有很多種方式,我會介紹兩種。

網址自動跳轉

搬家後,我們想要讓別人不再去使用舊的網址,就算它們使用舊的網址也會被強制帶到新的網址上,我們有很多實踐的方法,我這裡就挑一個繞路的,跟一個最最最簡單的方法。

先來講繞路的,繞路的好處是可以讓對方知道我們換網址了,適用已經經營很久的網站,很多人都已經記住你們的網址,就可以用這招。

首先我們先在域名供應商那裡把舊域名指向新主機(這步驟非必要),然後我們可以去創造一個nginx conf來解析它,或者如果沒有改到新主機,我們就看就得配置下wordpress所使用的資料夾是哪一個,如果是指向新主機請照我這樣做:

1
nano /etc/nginx/conf.d/old.domain.conf

添加以下內容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server {
    listen 80;

    server_name old.domain.com;
    
    root /var/www/old.domain.com/html;
    index index.html;

    location / {
		try_files $uri $uri/ =404;
    }
    
}

接著我們在/var/www/old.domain.com/html,創建一個index.html,而如果是打算用舊的主機做這件事情,則是把/your/wordpress/path/底下的index.php先改成_index.php後創造一個index.html

1
2
3
4
5
6
mkidr -p /var/www/old.domain.com/html
nano /var/www/old.domain.com/html/index.html

//使用舊主機
mv /your/wordpress/path/index.php /your/wordpress/path/_index.php
nano /your/wordpress/path/index.html

然後編輯它,添加以下內容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=new.domain.com">
</head>
<body>
</body>

// 如果想要讓大家看到你搬家了 則可以修改成以下內容

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="5; url=https://new.domain.com">
</head>
<body>
<h1>我搬家了,五秒後會自動跳到新的網站</h1>
<a href="https://new.domain.com">如果沒有跳轉到new.domain.com,請點選一下</a>
</body>

然後新主機上可能會碰上不安全網站問題,那就用certbot –nginx一下配置證書,應就沒問題了。

接著另外一個方法就是直接在域名供應商設定一下cname就好了。
old.domain.com cname new.domain.com
如此以來就交由DNS去煩惱自動轉址的事情囉,而新主機就不用去負責這個解析問題。

就這樣三篇打完了,謝謝各位。