thumbnail
快捷入口!使用docker部署web应用,通过REST API发布WordPress文章

引言

技术上来说,我的这个小站是个非法网站,备案是一概没有的,也不打算有。它整个都部署在外网VPS上,加载速度多少还是有点那个什么。坐下来认真写文章和评论的时候还好,但说说这种闲着没事记录想法的东西就很难容忍漫长的加载了。我考虑过使用电子邮件发布,但写电邮需要的行动力并没有低到哪里去。在打通大内网并且试用了一下Memos之后,使用docker在家里的服务器上部署一个web应用来做这件事就成了一个很自然的路线。

我在大概10个小时前还对docker、flask和html几乎没有了解——建站时学习的html知识早忘了,所以又要依赖强力的G老师了!

前置准备

需要Wordpress站点的应用密码,可以在用户选项里面创建。

需要开启Wordpress的REST API,默认一般是开启的,但是要修改固定链接模式为简单之外的任何模式。

需要测试一下REST API,链接大致是:

https://example.com/wp-json/wp/v2/posts

https://example.com/index.php/wp-json/wp/v2/posts

之类的,如果访问这种链接能够看到一大段类似rss订阅结果的文本就是成功了。

需要一台部署了docker的服务器,安装python和Flask。最好装个1Panel之类的面板,真的会方便很多,我们GUI时代成长起来的就是这样……

(可选)下载iziToast的css和js文件,用于显示发布成功或失败的提示信息。由于主站用了这个插件,所以就路径依赖了。

部署前端

在服务器上创建一个目录,比如/home/wp_post,作为docker打包的目录,整个目录结构如下,缺少的文件自己创建一下。

wp_post
├─ app.py
├─ Dockerfile
├─ templates
│ └─ index.html
└─ static
   ├─ logo.png
   ├─ iziToast.min.css
   └─ iziToast.min.js

其中app.py是后端逻辑,Dockerfile是docker镜像的构建文件,templates和static目录分别存放网页模板和静态资源。static其实是可有可无的,但为了美化还是加上去好。

创建完文件后,打开index.html,写入:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网页标题</title>
    <link rel="icon" href="{{ url_for('static', filename='logo.png') }}" type="image/png">
    <!-- Argon CSS -->
    <link href="{{ url_for('static', filename='argon.css') }}" rel="stylesheet">
    <link rel="stylesheet" href="{{ url_for('static', filename='iziToast.min.css') }}">
    <script src="{{ url_for('static', filename='iziToast.min.js') }}"></script>
    <style>
        body, html {
            height: 100%;
            margin: 0;
            background-color: #f7f7f7;
            font-family: 'Nunito', sans-serif;
        }
        .main-content {
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
        }
        .form-group textarea {
            width: 80%; /* Adjusted width */
            height: 60vh; /* 70% of the viewport height */
            margin: 0 auto; /* Centering the textarea */
            border: 2px solid #5e72e4;
            border-radius: 15px;
            padding: 20px; /* Padding inside the textarea */
            transition: border-color 0.3s ease;
            resize: none; /* Prevent resizing */
        }
        .form-group textarea:focus {
            border-color: #2dce89;
            box-shadow: none;
        }
        .btn-submit {
            background-color: #5e72e4;
            color: white;
            border-radius: 20px;
            border: none;
            padding: 10px 24px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: background-color 0.3s ease;
            margin-top: 20px; /* Space between textarea and button */
        }
        .btn-submit:hover {
            background-color: #4b60d6;
        }
    </style>
</head>
<body>
    <div class="main-content">
        <h2>说句话吧</h2>
        <form action="/post_article" method="post" style="width: 100%; max-width: 600px;">
            <div class="form-group">
                <textarea class="form-control" id="content" name="content" placeholder="文本框提示内容"></textarea>
            </div>
            <div>
                <button type="submit" class="btn-submit">发布按钮文字</button>
            </div>
        </form>
    </div>
    <!-- Argon JS -->
    <script src="{{ url_for('static', filename='argon.js') }}"></script>
    <script>
    document.querySelector('form').addEventListener('submit', function(e) {
        e.preventDefault();
        var formData = new FormData(this);
        fetch('/post_article', {
            method: 'post',
            body: formData
        }).then(response => response.json()).then(data => {
            if(data.success) {
                iziToast.success({
                    title: '发布成功',
                    message: data.message,
                    position: 'topCenter', // 设置通知位置为页面正上方
                    timeout: 3000 // 通知显示时间(毫秒)
                });
            } else {
                iziToast.error({
                    title: '发布失败',
                    message: data.message,
                    position: 'topCenter', // 设置通知位置为页面正上方
                    timeout: 3000 // 通知显示时间(毫秒)
                });
            }
        }).catch(error => {
            iziToast.error({
                title: '未知错误',
                message: '未知错误提示信息',
                position: 'topCenter', // 设置通知位置为页面正上方
                timeout: 3000 // 通知显示时间(毫秒)
            });
        });
    });
    </script>
</body>
</html>

这个页面同时包含了发布功能和提示功能。由于我发布的想法不需要标题所以省略掉了。在head里面还包含了指定iziToast css和js文件以及网站logo的功能。这里的logo最好是一个32*32的png之类的文件,如果改成icon的话要同步更改type,这不是本文的重点,相关资料也可以轻易地搜索到,不再赘述。

至此完成了前端部署。

部署后端

首先修改Dockerfile:

# 使用Python官方镜像作为基础镜像
FROM python:3.8-alpine
# 设置工作目录
WORKDIR /app
# 复制当前目录下的所有文件到容器内的/app目录
COPY . /app
# 安装Flask和requests
RUN pip install Flask requests
# 告诉Docker在容器启动时运行Python应用
CMD ["python", "./app.py"]

然后修改app.py:

from flask import Flask, render_template, request, redirect, url_for, jsonify
import requests
import base64
app = Flask(__name__)
# Home route
@app.route('/')
def home():
    return render_template('index.html')
# Route to post an article
@app.route('/post_article', methods=['POST'])
def post_article():
    #准备请求数据
    content = request.form['content']
    article_data = {'title': content, 'content': content, 'status': 'publish'}
    # 登录信息
    wp_url = "REST API请求链接"
    username = "Wordpress登陆用户名"
    app_password = "Wordpress应用密码"
    # 编码登录信息
    token = base64.b64encode(f"{username}:{app_password}".encode()).decode("utf-8")
    headers = {'Authorization': 'Basic ' + token}
    # 向WordPress REST API发送POST请求
    response = requests.post(wp_url, headers=headers, json=article_data)
    # 根据响应状态码判断是否成功
    if response.status_code == 201:
        # 成功
        return jsonify({"success": True, "message": "发布成功提示信息"})
    else:
        # 失败
        error_message = response.json().get('message', '发布失败提示信息')
        return jsonify({"success": False, "message": error_message})
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

将REST API链接、登录用户名和应用密码填入相应的位置,即完成后端设置。

创建并运行docker

连接到服务器,使用sudo -i获得root权限,然后确认docker状态:

systemctl status docker

进入刚才的目录:

cd /home/wp_post

打包镜像:

docker build -t <image name> .

最后这个点还挺重要的,没他不行。
运行镜像:

docker run -d -p <对外端口号>:5000 <image name>

这里面当然省略了很多东西,比如指定内部端口号啊之类的,但是这样就能跑了,之后可以在GUI面板进行重命名啊之类的管理。现在访问服务器ip:port应该可以看到一个正常工作的页面了。
收工!又水了一篇!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇