配置文件docker-compose.yml

使用docker-compose创建项目,docker-compose.yml内容如下:

services:
  mariadb:
    image: linuxserver/mariadb
    container_name: mariadb
    environment:
      - PUID=1000
      - PGID=1001
      - MYSQL_ROOT_PASSWORD=110119asdF!
      - MYSQL_DATABASE=typecho
      - MYSQL_USER=typecho
      - MYSQL_PASSWORD=TypechoPass123!
      - TZ=Asia/Shanghai
    volumes:
      - /vol2/1000/docker/MariaDB/config:/config
    ports:
      - 33306:3306
    networks:
      - mynet
    restart: unless-stopped

  adminer:
    image: adminer:latest
    container_name: adminer
    environment:
      - ADMINER_DEFAULT_SERVER=mariadb
    ports:
      - 38079:8080
    networks:
      - mynet
    depends_on:
      - mariadb
    restart: unless-stopped

  typecho:
    image: joyqi/typecho:nightly-php8.2-apache
    container_name: typecho-server
#    user: "1000:1001"
    restart: always
    environment:
      - TYPECHO_SITE_URL=http://192.168.199.20
      - TYPECHO_DB_ADAPTER=Pdo_Mysql
      - TYPECHO_DB_HOST=mariadb
      - TYPECHO_DB_PORT=3306
      - TYPECHO_DB_NAME=typecho
      - TYPECHO_DB_USER=typecho
      - TYPECHO_DB_PASSWORD=TypechoPass123!
    ports:
      - 38080:80
    networks:
      - mynet
    depends_on:
      - mariadb
    volumes:
      - /vol2/1000/docker/Typecho/usr:/app/usr
#      - /vol2/1000/docker/Typecho/uploads:/app/usr/uploads
#      - /vol2/1000/docker/Typecho/config.inc.php:/app/config.inc.php

networks:
  mynet:
    name: mynet

以上yml文件的原始文件有问题,注释掉那三行后,出现/app/usr/uploads/权限问题,加入以下命令解决

# 进入容器检查上传目录权限
docker exec typecho-server ls -la /app/usr/uploads/

# 在容器内直接设置权限(使用 root 权限)
docker exec -u root typecho-server chown -R www-data:www-data /app/usr/uploads/
docker exec -u root typecho-server chmod -R 777 /app/usr/uploads/

# 验证权限
docker exec typecho-server ls -la /app/usr/uploads/

# 测试写入权限
docker exec typecho-server touch /app/usr/uploads/test_file.txt
docker exec typecho-server ls -la /app/usr/uploads/
  • 然后我就问了一下ChatGPT和Deepseek为什么会这样,它的回答如下:

    ChatGPT的分析

    从你提供的内容来看,解决成功的原因是你通过手动调整了容器内 /app/usr/uploads/ 目录的 权限问题,这导致了最初的 500 错误权限拒绝 问题。

关键点分析:

  1. 权限问题

    • 原本 Typecho 容器启动时,尝试写入 /app/usr/uploads/ 和其他目录(比如 /app 目录),但是容器中的默认用户(通常是 www-data)没有足够的权限写入这些目录。
    • 在你没有挂载这些目录之前,镜像内部自带的目录结构是完好的,但一旦你挂载了宿主机的目录,特别是像 uploads 这样的目录,它可能默认是宿主机上 root:root 权限,导致容器无法正确写入。
  2. 通过命令修改权限解决问题

    docker exec -u root typecho-server chown -R www-data:www-data /app/usr/uploads/
    docker exec -u root typecho-server chmod -R 777 /app/usr/uploads/
    • chown -R www-data:www-data:把 /app/usr/uploads/ 目录的拥有者和组改成容器内运行的默认用户(www-data),这确保了 Typecho 进程能访问这些文件。
    • chmod -R 777:把权限设置为可读写执行,确保容器内的进程(如 Apache 或 PHP)有足够权限进行文件操作。
  3. 通过 lstouch 命令确认修改

    • 你通过 ls 命令检查了 /app/usr/uploads/ 目录,确认权限修改成功。
    • 使用 touch 命令尝试创建一个文件 test_file.txt,并成功创建,进一步确认了容器内的写入权限问题已解决。

总结原因:

  • 权限问题:因为宿主机上的挂载目录(如 /vol2/1000/docker/Typecho/usr)默认权限是 root:root,而容器的 PHP/Apache 是以 www-data 用户身份运行,导致容器无法写入这些目录。
  • 你通过手动修改权限后,解决了容器与宿主机之间的权限问题,使得 Typecho 能够正常操作这些目录。

防止未来出现类似问题:

  1. 确保正确的权限设置
    如果以后继续使用挂载卷,确保挂载的目录具有正确的权限。你可以在挂载前设置权限:

    sudo chown -R 1000:1001 /vol2/1000/docker/Typecho/usr
    sudo chmod -R 777 /vol2/1000/docker/Typecho/uploads

    这样在启动时,容器就能自动访问这些目录。

  2. 不直接使用 777 权限
    虽然 777 可以解决权限问题,但它会让文件对所有用户可读写。建议只给容器运行用户(如 www-data)提供权限:

    sudo chown -R www-data:www-data /vol2/1000/docker/Typecho/uploads
  3. Docker 用户配置
    如果你要使用挂载卷,建议通过 docker-compose.yml 中的 user 配置明确指定容器内的用户,确保宿主机和容器的用户一致,避免权限不匹配的问题。

Deepseek的分析

  • 成功原因分析

1. 移除了有问题的配置

您注释掉了以下有问题的配置:

yaml

# user: "1000:1001"  # ← 这行阻止了容器内初始化脚本以root权限运行
# - /vol2/1000/docker/Typecho/uploads:/app/usr/uploads  # ← 这会导致重复挂载
# - /vol2/1000/docker/Typecho/config.inc.php:/app/config.inc.php  # ← 可能覆盖重要文件

2. 正确的挂载策略

现在只挂载了:

yaml

volumes:
  - /vol2/1000/docker/Typecho/usr:/app/usr

这样:

  • 容器内的 /app/usr 目录被持久化到宿主机
  • 但容器仍然可以以自己的用户(包括root)运行初始化脚本
  • 不会覆盖其他核心文件

3. 权限修复的关键步骤

您执行的命令解决了根本问题:

bash

# 将uploads目录的所有权改为Apache运行用户
docker exec -u root typecho-server chown -R www-data:www-data /app/usr/uploads/

# 设置完全可读写权限
docker exec -u root typecho-server chmod -R 777 /app/usr/uploads/

为什么之前会失败?

  1. 用户配置冲突user: "1000:1001" 让容器以非root用户运行,但初始化脚本需要root权限来复制文件和设置权限
  2. 挂载覆盖:单独挂载uploads目录可能导致路径冲突或权限问题
  3. 所有权不匹配:宿主机目录的所有权(zhang:Users)与容器内Apache用户(www-data)不匹配

现在的健康状态

从您的测试结果看:

  • /app/usr/uploads/ 目录存在且可访问
  • ✅ 所有权正确设置为 www-data:www-data
  • ✅ 权限设置为 777(完全可读写)
  • ✅ 能够成功创建测试文件 test_file.txt

建议的最终配置

保持当前的简化配置:

yaml

typecho:
  image: joyqi/typecho:nightly-php8.2-apache
  container_name: typecho-server
  restart: always
  environment:
    - TYPECHO_SITE_URL=http://192.168.199.20
    - TYPECHO_DB_ADAPTER=Pdo_Mysql
    - TYPECHO_DB_HOST=mariadb
    - TYPECHO_DB_PORT=3306
    - TYPECHO_DB_NAME=typecho
    - TYPECHO_DB_USER=typecho
    - TYPECHO_DB_PASSWORD=TypechoPass123!
  ports:
    - 38080:80
  networks:
    - mynet
  depends_on:
    - mariadb
  volumes:
    - /vol2/1000/docker/Typecho/usr:/app/usr  # 只挂载这个

安装完成后的操作

安装完成后,可以考虑恢复更安全的权限:

bash

# 设置更安全的权限(但保持可写)
docker exec -u root typecho-server chmod -R 755 /app/usr/
docker exec -u root typecho-server chmod -R 775 /app/usr/uploads/

现在您可以刷新 Typecho 安装页面,应该可以正常完成安装了!

发表评论