分类: 技术笔记

记录开发过程中的经验、踩坑与问题解决方案

  • 使用 Docker Compose 管理容器服务

    在早期,我通过 docker run 命令手动运行容器,这在服务数量较少时尚可应付。但随着了解并使用的容器增多,手动创建变得低效且混乱。同时,先前发布过一次 Docker 常用服务相关代码,评论区也推荐我使用 Docker Compose。因此,我逐步迁移到使用 Docker Compose 进行容器编排,统一管理后端数据库、前端代理、开发应用与运维服务。

    本文整理并展示了我当前服务器上运行的主要容器配置,包括 nginx、mysql、wordpress、vaultwarden 等服务。相关配置需要配合 .env 文件变量,下面的内容部分细节只针对我的服务器调试,如果需要可能需根据你的服务器自行调整。如果你有优化或者更好的建议也可以在下面评论中与我进行沟通交流。

    docker-compose.yml

    # 定义两个自定义网络,实现服务间的隔离
    networks:
      backend:
        driver: bridge  # 后端服务间通信网络
      frontend:
        driver: bridge  # 前端服务与外部通信网络
    
    services:
      nginx:
        image: nginx
        container_name: nginx
        restart: always
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ${ROOT_PATH}/nginx/nginx.conf:/etc/nginx/nginx.conf
          - ${ROOT_PATH}/nginx/conf.d:/etc/nginx/conf.d
          - ${ROOT_PATH}/nginx/ssl:/etc/nginx/ssl
          - ${ROOT_PATH}/nginx/html:/usr/share/nginx/html
          - ${ROOT_PATH}/nginx/log:/var/log/nginx
        environment:
          - TZ=Asia/Shanghai
        labels:
          # Nginx 配合 acme.sh 自动加载证书,支持热更新。
          - sh.acme.autoload.domain=${CAME_SH_AUTOLOAD_DOMAIN}
        networks:
          - frontend
          - backend
        healthcheck:
          test: ["CMD-SHELL", "nginx -t || exit 1"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 10s
    
      mysql:
        image: mysql
        container_name: mysql
        restart: always
        expose:
          - "3306"
        volumes:
          - ${ROOT_PATH}/mysql/conf.d:/etc/mysql/conf.d
          - ${ROOT_PATH}/mysql/data:/var/lib/mysql
          - ${ROOT_PATH}/mysql/log:/var/log/mysql
        environment:
          - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
          - TZ=Asia/Shanghai
        command:
          - --lower_case_table_names=1
          - --sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
        networks:
          - backend
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      redis:
        image: redis:latest
        container_name: redis
        restart: always
        expose:
          - "6379"
        volumes:
          - ${ROOT_PATH}/redis/data:/data
          - ${ROOT_PATH}/redis/redis.conf:/usr/local/etc/redis/redis.conf
        command: redis-server /usr/local/etc/redis/redis.conf
        networks:
          - backend
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
          interval: 10s
          timeout: 3s
          retries: 3
      
      wordpress:
        image: wordpress:latest
        container_name: wordpress
        restart: always
        expose:
          - "80"
        volumes:
          - ${ROOT_PATH}/wordpress:/var/www/html
        environment:
          - WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME}
          - WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST}
          - WORDPRESS_DB_USER=${WORDPRESS_DB_USER}
          - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
        networks:
          - backend
        healthcheck:
          test: ["CMD-SHELL", "curl -s -o /dev/null -w '%{http_code}' http://localhost/wp-login.php | grep -qE '2[0-9]{2}|3[0-9]{2}|403|404' || exit 1"]
          interval: 30s
          timeout: 10s
          retries: 5
          start_period: 180s
        depends_on:
          mysql:
            condition: service_healthy
      
      phpmyadmin:
        image: phpmyadmin
        container_name: phpmyadmin
        restart: always
        expose:
          - "80"
        environment:
          - PMA_HOST=mysql
          - PMA_PORT=3306
          - TZ=Asia/Shanghai
        networks:
          - backend
        healthcheck:
          test: ["CMD", "curl", "-fsSL", "http://localhost"]
          interval: 30s
          timeout: 10s
          retries: 3
          start_period: 10s
        depends_on:
          mysql:
            condition: service_healthy
    
      vaultwarden:
        image: vaultwarden/server
        container_name: vaultwarden
        restart: always
        expose:
        - "80"
        volumes:
        - ${ROOT_PATH}/vaultwarden:/data
        environment:
        - DATABASE_URL=mysql://${VAULTWARDEN_DATABASE_USER}:${VAULTWARDEN_DATABASE_PASSWORD}@mysql/vaultwarden
        - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
        - RUST_BACKTRACE=1
        networks:
          - backend
        healthcheck:
          test: ["CMD", "curl", "-fsSL", "http://localhost"]
          interval: 30s
          timeout: 15s
          retries: 3
          start_period: 30s
        depends_on:
          mysql:
            condition: service_healthy
    
      acme.sh:
        image: neilpang/acme.sh
        container_name: acme.sh
        restart: always
        volumes:
          - ${ROOT_PATH}/acme.sh:/acme.sh
          - /var/run/docker.sock:/var/run/docker.sock:ro
        environment:
          - DP_Id=${CAME_SH_DNSPOD_ID}
          - DP_Key=${CAME_SH_DNSPOD_KEY}
          - DEPLOY_DOCKER_CONTAINER_LABEL=sh.acme.autoload.domain=${CAME_SH_AUTOLOAD_DOMAIN}
          - DEPLOY_DOCKER_CONTAINER_KEY_FILE="/etc/nginx/ssl/${CAME_SH_AUTOLOAD_DOMAIN}/${CAME_SH_AUTOLOAD_DOMAIN}.key"
          - DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/ssl/${CAME_SH_AUTOLOAD_DOMAIN}/${CAME_SH_AUTOLOAD_DOMAIN}.cer"
          - DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/ssl/${CAME_SH_AUTOLOAD_DOMAIN}/ca.cer"
          - DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/ssl/${CAME_SH_AUTOLOAD_DOMAIN}/fullchain.cer"
          - DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="docker compose exec nginx nginx -s reload"
        command: daemon
        networks:
          - backend
    
      watchtower:
        image: containrrr/watchtower
        container_name: watchtower
        restart: always
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
        environment:
          - TZ=Asia/Shanghai
        command:
          - --cleanup=true
        networks:
          - backend
      
      minecraft:
        image: itzg/minecraft-server
        container_name: minecraft-server
        restart: always
        tty: true
        stdin_open: true
        ports:
          - "25565:25565"
        environment:
          - EULA=TRUE
          - MAX_PLAYERS=8
          - TZ=Asia/Shanghai
          - DIFFICULTY=2
          - ENABLE_COMMAND_BLOCK=true
        volumes:
          - ${ROOT_PATH}/minecraft:/data
        networks:
          - backend
    
      beszel:
        image: henrygd/beszel:latest
        container_name: beszel
        restart: always
        expose:
          - "8090"
        volumes:
          - ${ROOT_PATH}/beszel:/beszel_data
        healthcheck:
          test: ['CMD', '/beszel', 'health', '--url', 'http://localhost:8090']
          start_period: 5s
          interval: 120s
        networks:
          - frontend
      
      beszel-agent:
        image: henrygd/beszel-agent:latest
        container_name: beszel-agent
        restart: always
        network_mode: host
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
        healthcheck:
          test: ['CMD', '/agent', 'health']
          start_period: 5s
          interval: 120s
        environment:
          PORT: 45876
          KEY: '<公钥>'

    自定义网络:

    backend 用于内部服务通信(MySQL、Redis、WordPress、Vaultwarden 等)

    frontend 用于暴露 Nginx、监控等对外服务

    .env 文件

    # 项目根路径映射(用于挂载)
    ROOT_PATH=/home/halon/apps
    
    # 域名配置
    # 替换为你的网站域名
    CAME_SH_AUTOLOAD_DOMAIN="example.com"
    
    # ACME DNSPod 证书自动签发
    CAME_SH_DNSPOD_ID="DNSPod ID"
    CAME_SH_DNSPOD_KEY="DNSPod Key"
    
    # MySQL 配置
    MYSQL_ROOT_PASSWORD="MySQL root 密码"
    
    # WordPress 数据库
    WORDPRESS_DB_NAME=WordPress 数据库名称
    WORDPRESS_DB_HOST=WordPress 数据库主机名称
    WORDPRESS_DB_USER=WordPress 数据库用户名
    WORDPRESS_DB_PASSWORD=WordPress 数据库密码
    
    # Vaultwarden 配置
    VAULTWARDEN_DATABASE_USER="Vaultwarden 数据库用户名"
    VAULTWARDEN_DATABASE_PASSWORD="Vaultwarden 数据库密码"
    VAULTWARDEN_ADMIN_TOKEN='Vaultwarden Admin Token'

    上述两个文件需要放置在一起,以供执行 Docker Compose 时能够寻找到相对应的变量。

  • WordPress 显示链接功能

    自 WordPress 3.5 版本以后,默认隐藏了“链接”的功能,如果我们需要添加友情链接,可以借助插件或者修改代码的方式进行操作。

    但如果你希望使用系统默认“链接”管理功能,但又不打算安装额外插件,可以通过添加一行代码的方式手动启用。

    启用方法

    将以下代码添加至当前主题的 functions.php 文件中(建议添加至文件末尾):

    add_filter('pre_option_link_manager_enabled', '__return_true');

    保存并更新文件后,WordPress 管理后台左侧菜单将会显示 “链接” 项目,即可开始管理和添加友情链接。

    这个方法适用于任何支持自定义 functions.php 的主题且不依赖插件,适合追求轻量纯净的个人博客用户。

  • 电信光猫 TEWA-708G 获取超级密码教程

    注意:这是一篇发表于2023年的文章,相关信息可能已更新,本文章仅供技术参考,部分操作方式可能有所改动,请读者自行甄别。

    我使用的是电信光猫 TEWA-708G,超级用户的密码已经不再是固定的了,是随机生成的,所以需要一些操作才能够获取到超级密码。

    这个教程不能保证适用所有型号为 TEWA-708G 的光猫,因为通过搜索有些同型号的光猫使用的是 sessionKey 进行查找,有些则是以 set1_sessionKey_*** 进行查找,我的设备使用的是 set1_sessionKey_***,所以做一个记录:

    使用普通用户登录

    用户名和密码在光猫的背面,登录地址:192.168.1.1:8080,用户名一般为 useradmin,并在光猫 USB 接口中插好 U 盘。

    进入“设备管理页面”

    点击“管理”—“设备管理”或访问:http://192.168.1.1:8080/MD_Device_user.html
    一定要确认进入设备管理界面,这个界面连 USB 都给屏蔽了。

    查找 set1_sessionKey_***

    按 F12 或在页面点右键→检查,然后在里面搜索 set1_sessionKey_,你会找到一个 set1_sessionKey_*** 之类的结果,把 *** 记下来。

    构造命令并执行

    切换到 Console 窗口,在输入框中输入如下内容:location.assign("/usbbackup.cmd?action=backupeble&set1_sessionKey=set1_sessionKey_***") 然后回车。

    备份配置

    页面打开后,右键备份配置,点击“检查”,删除 disable 字段,此时可以看到按钮已从禁用状态转为可点击状态,现在可以点击“备份配置”正常备份了,点击之后页面会全白,那是正常的。

    得到备份文件

    U 盘上会生成一个名为 e8_Config_Backup 的文件夹,其下的 ctce8_TEWA-708G.cfg 就是路由器配置文件。

    解密文件

    如果用记事本打开 ctce8_TEWA-708G.cfg,会是一堆乱码。要使用 xor(点击跳转 或者 router pass view 打开配置文件,搜索 TeleComAccount 字段 ,下面的 Password 内即为超级密码。

    关闭启用周期上报

    进入 Web 后台管理界面后,切换到“网络”—“远程管理”选项卡,清除勾选“启用周期上报”项,这样就彻底阻止了电信对光猫的远程控制功能。

    以上就是电信光猫 TEWA-708G 获取超级密码的整个教程,但不保证这个教程适用于这个光猫型号的所有设备,所以,如果按照上述操作发现无法获取超级密码则需要搜索其他获取方案。