找回密码
 立即注册
首页 业界区 业界 Podman + Nginx + Affine 踩坑教程

Podman + Nginx + Affine 踩坑教程

敕码 2025-9-24 13:56:44
安装 Podman

安装 podman 很简单
  1. sudo apt install podman
复制代码
验证安装
  1. podman info
复制代码
创建一个 pod 用于安装 Nginx 和 Affine
  1. podman pod create --name mypod -p 80:8080
复制代码
注意:需要在/etc/sysctl.conf中加入net.ipv4.ip_unprivileged_port_start=80才能创建 80 端口映射
安装 Nginx

创建对应的文件夹
  1. mkdir -p /opt/serves/nginx/app
  2. mkdir -p /opt/serves/nginx/conf
  3. mkdir -p /opt/serves/nginx/logs
复制代码
创建 bitnami 的 Nginx 容器
  1. podman run -d --pod mypod --name nginx \
  2. -v /opt/serves/nginx/app:/app \
  3. -v /opt/serves/nginx/conf:/opt/bitnami/nginx/conf \
  4. -v /opt/serves/nginx/logs:/opt/bitnami/nginx/logs \
  5. bitnami/nginx:latest
复制代码
需要注意的点:

  • 用--pod mypod将容器加入 pod 中
  • 浏览器访问http://IP检查 Nginx 是否正常运行
安装 Affine

创建对应的文件夹
  1. mkdir -p /opt/serves/affine/postgres/pgdata
  2. mkdir -p /opt/serves/affine/storage
  3. mkdir -p /opt/serves/affine/config
复制代码
通过 podman 命令安装 affine

虽然 Affine 官方提供了 docker-compose.yaml 文件,但是 podman comopse 无法直接将创建的容器加入 pod 中,因此需要用对应的命令逐个创建容器。
这是官方提供的 compose 和 env 文件,我们不使用它们,而是直接把环境变量和参数在命令行中设置好

  • docker-compose.yaml
  1. name: affine
  2. services:
  3.   affine:
  4.     image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
  5.     container_name: affine_server
  6.     # ports:
  7.     #   - '${PORT:-3010}:3010'
  8.     depends_on:
  9.       redis:
  10.         condition: service_healthy
  11.       postgres:
  12.         condition: service_healthy
  13.       affine_migration:
  14.         condition: service_completed_successfully
  15.     volumes:
  16.       # custom configurations
  17.       - ${UPLOAD_LOCATION}:/root/.affine/storage
  18.       - ${CONFIG_LOCATION}:/root/.affine/config
  19.     env_file:
  20.       - .env
  21.     environment:
  22.       - REDIS_SERVER_HOST=redis
  23.       - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
  24.       - AFFINE_INDEXER_ENABLED=false
  25.     restart: unless-stopped
  26.   affine_migration:
  27.     image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
  28.     container_name: affine_migration_job
  29.     volumes:
  30.       # custom configurations
  31.       - ${UPLOAD_LOCATION}:/root/.affine/storage
  32.       - ${CONFIG_LOCATION}:/root/.affine/config
  33.     command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
  34.     env_file:
  35.       - .env
  36.     environment:
  37.       - REDIS_SERVER_HOST=redis
  38.       - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
  39.       - AFFINE_INDEXER_ENABLED=false
  40.     depends_on:
  41.       postgres:
  42.         condition: service_healthy
  43.       redis:
  44.         condition: service_healthy
  45.   redis:
  46.     image: redis
  47.     container_name: affine_redis
  48.     healthcheck:
  49.       test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
  50.       interval: 10s
  51.       timeout: 5s
  52.       retries: 5
  53.     restart: unless-stopped
  54.   postgres:
  55.     image: pgvector/pgvector:pg16
  56.     container_name: affine_postgres
  57.     volumes:
  58.       - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
  59.     environment:
  60.       POSTGRES_USER: ${DB_USERNAME}
  61.       POSTGRES_PASSWORD: ${DB_PASSWORD}
  62.       POSTGRES_DB: ${DB_DATABASE:-affine}
  63.       POSTGRES_INITDB_ARGS: '--data-checksums'
  64.       # you better set a password for you database
  65.       # or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
  66.       POSTGRES_HOST_AUTH_METHOD: trust
  67.     healthcheck:
  68.       test:
  69.         ['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
  70.       interval: 10s
  71.       timeout: 5s
  72.       retries: 5
  73.     restart: unless-stopped
复制代码

  • .env
  1. # select a revision to deploy, available values: stable, beta, canary
  2. AFFINE_REVISION=stable
  3. # set the port for the server container it will expose the server on
  4. PORT=3010
  5. # set the host for the server for outgoing links
  6. # AFFINE_SERVER_HTTPS=true
  7. # AFFINE_SERVER_HOST=affine.yourdomain.com
  8. # or
  9. # AFFINE_SERVER_EXTERNAL_URL=https://affine.yourdomain.com
  10. # position of the database data to persist
  11. DB_DATA_LOCATION=/opt/serves/affine/postgres/pgdata
  12. # position of the upload data(images, files, etc.) to persist
  13. UPLOAD_LOCATION=/opt/serves/affine/storage
  14. # position of the configuration files to persist
  15. CONFIG_LOCATION=/opt/serves/affine/config
  16. # database credentials
  17. DB_USERNAME=affine
  18. DB_PASSWORD=[你的密码]
  19. DB_DATABASE=affine
复制代码
创建 Redis 容器

通过观察compose文件,可以看出我们需要创建 Redis、Postgres、Affine Migration 和 Affine Server 四个容器,我们从 Redis 开始
Redis 对应的部分是:
  1.   redis:
  2.     image: redis
  3.     container_name: affine_redis
  4.     healthcheck:
  5.       test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
  6.       interval: 10s
  7.       timeout: 5s
  8.       retries: 5
  9.     restart: unless-stopped
复制代码
转换成 podman 命令就是:
  1. podman run -d --pod mypod --name affine_redis \
  2. --restart unless-stopped \
  3. --health-cmd "redis-cli --raw incr ping" \
  4. --health-interval 10s \
  5. --health-timeout 5s \
  6. --health-retries 5 redis
复制代码
可以看到创建 Redis 容器还是比较简单的,没有什么需要配置的地方
创建 Postgres 容器

不需要等待 Redis 运行,继续创建 Postgres 容器
Postgres 对应的部分是:
  1.   postgres:
  2.     image: pgvector/pgvector:pg16
  3.     container_name: affine_postgres
  4.     volumes:
  5.       - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
  6.     environment:
  7.       POSTGRES_USER: ${DB_USERNAME}
  8.       POSTGRES_PASSWORD: ${DB_PASSWORD}
  9.       POSTGRES_DB: ${DB_DATABASE:-affine}
  10.       POSTGRES_INITDB_ARGS: '--data-checksums'
  11.       # you better set a password for you database
  12.       # or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
  13.       POSTGRES_HOST_AUTH_METHOD: trust
  14.     healthcheck:
  15.       test:
  16.         ['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
  17.       interval: 10s
  18.       timeout: 5s
  19.       retries: 5
  20.     restart: unless-stopped
复制代码
转换后的 podman 命令明显比 Redis 长了很多:
  1. podman run -d --pod mypod --name affine_postgres \                                                           --restart unless-stopped \
  2.   -v /opt/serves/affine/postgres/pgdata:/var/lib/postgresql/data \
  3.   -e POSTGRES_USER=affine \
  4.   -e POSTGRES_PASSWORD=[你的密码] \
  5.   -e POSTGRES_DB=affine \
  6.   -e POSTGRES_INITDB_ARGS='--data-checksums' \
  7.   -e POSTGRES_HOST_AUTH_METHOD=trust \
  8.   --health-cmd "pg_isready -U affine -d affine" \
  9.   --health-interval 10s --health-timeout 5s --health-retries 5 \
  10.   pgvector/pgvector:pg16
复制代码
需要注意的地方:

  • 把DB_USERNAME、DB_PASSWORD这些环境变量替换为真实的用户名、密码...
创建 Affine Migration 容器

在执行这一步之前需要等待 Redis 和 Postgres 的状态转变为healthy,可以通过podman ps查看这两个容器的状态
Affine Migration 对应的部分是:
  1.   affine_migration:
  2.     image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
  3.     container_name: affine_migration_job
  4.     volumes:
  5.       # custom configurations
  6.       - ${UPLOAD_LOCATION}:/root/.affine/storage
  7.       - ${CONFIG_LOCATION}:/root/.affine/config
  8.     command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
  9.     env_file:
  10.       - .env
  11.     environment:
  12.       - REDIS_SERVER_HOST=redis
  13.       - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
  14.       - AFFINE_INDEXER_ENABLED=false
  15.     depends_on:
  16.       postgres:
  17.         condition: service_healthy
  18.       redis:
  19.         condition: service_healthy
复制代码
转换后的 podman 命令为:
  1. podman run --rm --pod mypod --name affine_migration_job \
  2.   -v /opt/serves/affine/storage:/root/.affine/storage \
  3.   -v /opt/serves/affine/config:/root/.affine/config \
  4.   -e REDIS_SERVER_HOST=localhost \
  5.   -e DATABASE_URL=postgresql://affine:[密码]@affine_postgres:5432/$affine \
  6.   -e AFFINE_INDEXER_ENABLED=false \
  7.   ghcr.io/toeverything/affine:stable \
  8.   sh -c 'node ./scripts/self-host-predeploy.js'
复制代码
这其实是一个数据迁移步骤,执行完毕后用podman ps也不会看到相关容器,不必担心,需要注意的是:

  • 由于所有容器都在一个 pod 中,REDIS_SERVER_HOST直接设置为localhost即可
  • 如果出现User was denied access on the database错误,进入 postgres 容器创建对应数据库
  1. # 1. 进入容器
  2. podman exec -it affine_postgres psql -U postgres
  3. # 2. 确认用户是否存在
  4. \du
  5. # 3. 如果没有 affine 用户,请创建:
  6. CREATE USER affine WITH PASSWORD '19970614yao';
  7. # 4. 创建数据库并授权
  8. CREATE DATABASE affine OWNER affine;
  9. GRANT ALL PRIVILEGES ON DATABASE affine TO affine;
  10. # 5. 刷新权限
  11. FLUSH PRIVILEGES;
  12. # 6. 退出数据库后重新运行创建affine_migration_job容器即可
复制代码
创建 Affine Server 容器

终于到了部署 Affine 的最后一步
Affine Migration 对应的部分是:
  1.   affine:
  2.     image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
  3.     container_name: affine_server
  4.     ports:
  5.       - '${PORT:-3010}:3010'
  6.     depends_on:
  7.       redis:
  8.         condition: service_healthy
  9.       postgres:
  10.         condition: service_healthy
  11.       affine_migration:
  12.         condition: service_completed_successfully
  13.     volumes:
  14.       # custom configurations
  15.       - ${UPLOAD_LOCATION}:/root/.affine/storage
  16.       - ${CONFIG_LOCATION}:/root/.affine/config
  17.     env_file:
  18.       - .env
  19.     environment:
  20.       - REDIS_SERVER_HOST=redis
  21.       - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
  22.       - AFFINE_INDEXER_ENABLED=false
  23.     restart: unless-stopped
复制代码
转换后的 podman 命令为:
  1. podman run -d --pod mypod --name affine_server \
  2.   --restart unless-stopped \
  3.   -v /opt/serves/affine/storage:/root/.affine/storage \
  4.   -v /opt/serves/affine/config:/root/.affine/config \
  5.   -e REDIS_SERVER_HOST=localhost \
  6.   -e DATABASE_URL=postgresql://affine:[密码]@localhost:5432/affine \
  7.   -e AFFINE_INDEXER_ENABLED=false \
  8.   ghcr.io/toeverything/affine:stable
复制代码
运行podman logs affine_server检查运行情况,应该有如下输出:
  1. LOG [NestApplication] Nest application successfully started
  2. LOG [WorkspaceResolver] AFFiNE Server is running in [selfhosted] mode
  3. LOG [WorkspaceResolver] Listening on http://0.0.0.0:3010
  4. LOG [WorkspaceResolver] And the public server should be recognized as http://localhost:3010
复制代码
要注意的是:

  • 由于 pod 统一映射了端口,不需要再设置端口映射
配置 Nginx 反向代理

终于我们完成了 Affine 的配置,接下来只要再配置 Nginx 反向代理让我们能访问 Affine 服务就行了
在/opt/serves/nginx/conf/server_blocks下新建一个affine.conf文件和一个default.conf文件

  • affine.conf
    用于把访问affine.your.domain的流量代理至 Affine 监听的 3010 端口
  1. server {
  2.     listen 8080;  # 映射的是pod外的80端口
  3.     server_name affine.your.domain;  # 只有通过这个域名访问的流量才会被代理至Affine
  4.     access_log /opt/bitnami/nginx/logs/affine.log;
  5.     error_log /opt/bitnami/nginx/logs/affine.log;
  6.     location / {
  7.         proxy_set_header X-Real-IP $remote_addr;
  8.         proxy_set_header HOST $http_host;
  9.         proxy_set_header X-NginX-Proxy true;
  10.         proxy_pass http://localhost:3010;  # 代理至 Affine监听的3010端口
  11.         proxy_redirect off;
  12.     }
  13. }
复制代码

  • default.conf
    用于屏蔽域名不匹配的流量(可选)
    当不是通过affine.your.domain访问服务器时,直接关闭连接
  1. server {
  2.     listen 8080 default_server;
  3.     server_name _;              # 匹配任何 Host
  4.     return 444;                 # 直接关闭连接(也可以 404 / 503)
  5. }
复制代码
完成上述步骤后,即可在浏览器中通过域名访问 affine 服务
注册 systemd 服务(推荐)

由于 podman 没有守护进程,所以没法开机自启动 pod 或容器,要借助 systemd 实现自启动
  1. podman generate systemd --name mypod --new --files
  2. # 会生成下面这些文件
  3. /opt/serves/container-doocs.service
  4. /opt/serves/container-affine_redis.service
  5. /opt/serves/container-affine_postgres.service
  6. /opt/serves/pod-mypod.service
  7. /opt/serves/container-affine_server.service
  8. /opt/serves/container-nginx.service
复制代码
把这些文件复制到用户的 systemd 目录下,没有这个目录就创建一个
  1. mkdir -p ~/.config/systemd/user  # 一般都有这个目录
  2. cp *.service ~/.config/systemd/user
复制代码
重载 systemd 并应用服务
  1. systemctl --user daemon-reload
  2. systemctl --user enable --now pod-mypod.service
复制代码
导出 pod 文件(推荐)

可以导出 pod 文件,这样下次再创建 pod 就不需要这么麻烦了
  1. podman generate kube mypod>mypod.yaml # 导出pod配置,兼容k8s
  2. podmam play kube mypod.yaml # 可以从yaml文件重新创建mod
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

3 天前

举报

感谢分享
您需要登录后才可以回帖 登录 | 立即注册