安装 Podman

安装 podman 很简单

sudo apt install podman

验证安装

podman info

创建一个 pod 用于安装 Nginx 和 Affine

podman pod create --name mypod -p 80:8080

注意:需要在/etc/sysctl.conf中加入net.ipv4.ip_unprivileged_port_start=80才能创建 80 端口映射

安装 Nginx

创建对应的文件夹

mkdir -p /opt/serves/nginx/app
mkdir -p /opt/serves/nginx/conf
mkdir -p /opt/serves/nginx/logs

创建 bitnami 的 Nginx 容器

podman run -d --pod mypod --name nginx \
-v /opt/serves/nginx/app:/app \
-v /opt/serves/nginx/conf:/opt/bitnami/nginx/conf \
-v /opt/serves/nginx/logs:/opt/bitnami/nginx/logs \
bitnami/nginx:latest

需要注意的点:

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

安装 Affine

创建对应的文件夹

mkdir -p /opt/serves/affine/postgres/pgdata
mkdir -p /opt/serves/affine/storage
mkdir -p /opt/serves/affine/config

通过 podman 命令安装 affine

虽然 Affine 官方提供了 docker-compose.yaml 文件,但是 podman comopse 无法直接将创建的容器加入 pod 中,因此需要用对应的命令逐个创建容器。

这是官方提供的 compose 和 env 文件,我们不使用它们,而是直接把环境变量和参数在命令行中设置好

  • docker-compose.yaml
name: affine
services:
affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_server
# ports:
# - '${PORT:-3010}:3010'
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
affine_migration:
condition: service_completed_successfully
volumes:
# custom configurations
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
restart: unless-stopped affine_migration:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_migration_job
volumes:
# custom configurations
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
env_file:
- .env
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy redis:
image: redis
container_name: affine_redis
healthcheck:
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped postgres:
image: pgvector/pgvector:pg16
container_name: affine_postgres
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE:-affine}
POSTGRES_INITDB_ARGS: '--data-checksums'
# you better set a password for you database
# or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
POSTGRES_HOST_AUTH_METHOD: trust
healthcheck:
test:
['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
  • .env
# select a revision to deploy, available values: stable, beta, canary
AFFINE_REVISION=stable # set the port for the server container it will expose the server on
PORT=3010 # set the host for the server for outgoing links
# AFFINE_SERVER_HTTPS=true
# AFFINE_SERVER_HOST=affine.yourdomain.com
# or
# AFFINE_SERVER_EXTERNAL_URL=https://affine.yourdomain.com # position of the database data to persist
DB_DATA_LOCATION=/opt/serves/affine/postgres/pgdata
# position of the upload data(images, files, etc.) to persist
UPLOAD_LOCATION=/opt/serves/affine/storage
# position of the configuration files to persist
CONFIG_LOCATION=/opt/serves/affine/config # database credentials
DB_USERNAME=affine
DB_PASSWORD=[你的密码]
DB_DATABASE=affine
创建 Redis 容器

通过观察compose文件,可以看出我们需要创建 Redis、Postgres、Affine Migration 和 Affine Server 四个容器,我们从 Redis 开始

Redis 对应的部分是:

  redis:
image: redis
container_name: affine_redis
healthcheck:
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped

转换成 podman 命令就是:

podman run -d --pod mypod --name affine_redis \
--restart unless-stopped \
--health-cmd "redis-cli --raw incr ping" \
--health-interval 10s \
--health-timeout 5s \
--health-retries 5 redis

可以看到创建 Redis 容器还是比较简单的,没有什么需要配置的地方

创建 Postgres 容器

不需要等待 Redis 运行,继续创建 Postgres 容器

Postgres 对应的部分是:

  postgres:
image: pgvector/pgvector:pg16
container_name: affine_postgres
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE:-affine}
POSTGRES_INITDB_ARGS: '--data-checksums'
# you better set a password for you database
# or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
POSTGRES_HOST_AUTH_METHOD: trust
healthcheck:
test:
['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped

转换后的 podman 命令明显比 Redis 长了很多:

podman run -d --pod mypod --name affine_postgres \                                                           --restart unless-stopped \
-v /opt/serves/affine/postgres/pgdata:/var/lib/postgresql/data \
-e POSTGRES_USER=affine \
-e POSTGRES_PASSWORD=[你的密码] \
-e POSTGRES_DB=affine \
-e POSTGRES_INITDB_ARGS='--data-checksums' \
-e POSTGRES_HOST_AUTH_METHOD=trust \
--health-cmd "pg_isready -U affine -d affine" \
--health-interval 10s --health-timeout 5s --health-retries 5 \
pgvector/pgvector:pg16

需要注意的地方:

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

在执行这一步之前需要等待 Redis 和 Postgres 的状态转变为healthy,可以通过podman ps查看这两个容器的状态

Affine Migration 对应的部分是:

  affine_migration:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_migration_job
volumes:
# custom configurations
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
env_file:
- .env
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy

转换后的 podman 命令为:

podman run --rm --pod mypod --name affine_migration_job \
-v /opt/serves/affine/storage:/root/.affine/storage \
-v /opt/serves/affine/config:/root/.affine/config \
-e REDIS_SERVER_HOST=localhost \
-e DATABASE_URL=postgresql://affine:[密码]@affine_postgres:5432/$affine \
-e AFFINE_INDEXER_ENABLED=false \
ghcr.io/toeverything/affine:stable \
sh -c 'node ./scripts/self-host-predeploy.js'

这其实是一个数据迁移步骤,执行完毕后用podman ps也不会看到相关容器,不必担心,需要注意的是:

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

终于到了部署 Affine 的最后一步

Affine Migration 对应的部分是:

  affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_server
ports:
- '${PORT:-3010}:3010'
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
affine_migration:
condition: service_completed_successfully
volumes:
# custom configurations
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
restart: unless-stopped

转换后的 podman 命令为:

podman run -d --pod mypod --name affine_server \
--restart unless-stopped \
-v /opt/serves/affine/storage:/root/.affine/storage \
-v /opt/serves/affine/config:/root/.affine/config \
-e REDIS_SERVER_HOST=localhost \
-e DATABASE_URL=postgresql://affine:[密码]@localhost:5432/affine \
-e AFFINE_INDEXER_ENABLED=false \
ghcr.io/toeverything/affine:stable

运行podman logs affine_server检查运行情况,应该有如下输出:

LOG [NestApplication] Nest application successfully started
LOG [WorkspaceResolver] AFFiNE Server is running in [selfhosted] mode
LOG [WorkspaceResolver] Listening on http://0.0.0.0:3010
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 端口
server {
listen 8080; # 映射的是pod外的80端口
server_name affine.your.domain; # 只有通过这个域名访问的流量才会被代理至Affine
access_log /opt/bitnami/nginx/logs/affine.log;
error_log /opt/bitnami/nginx/logs/affine.log; location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true; proxy_pass http://localhost:3010; # 代理至 Affine监听的3010端口
proxy_redirect off;
}
}
  • default.conf

    用于屏蔽域名不匹配的流量(可选)

    当不是通过affine.your.domain访问服务器时,直接关闭连接
server {
listen 8080 default_server;
server_name _; # 匹配任何 Host
return 444; # 直接关闭连接(也可以 404 / 503)
}

完成上述步骤后,即可在浏览器中通过域名访问 affine 服务

注册 systemd 服务(推荐)

由于 podman 没有守护进程,所以没法开机自启动 pod 或容器,要借助 systemd 实现自启动

podman generate systemd --name mypod --new --files

# 会生成下面这些文件
/opt/serves/container-doocs.service
/opt/serves/container-affine_redis.service
/opt/serves/container-affine_postgres.service
/opt/serves/pod-mypod.service
/opt/serves/container-affine_server.service
/opt/serves/container-nginx.service

把这些文件复制到用户的 systemd 目录下,没有这个目录就创建一个

mkdir -p ~/.config/systemd/user  # 一般都有这个目录
cp *.service ~/.config/systemd/user

重载 systemd 并应用服务

systemctl --user daemon-reload
systemctl --user enable --now pod-mypod.service

导出 pod 文件(推荐)

可以导出 pod 文件,这样下次再创建 pod 就不需要这么麻烦了

podman generate kube mypod>mypod.yaml # 导出pod配置,兼容k8s
podmam play kube mypod.yaml # 可以从yaml文件重新创建mod

Podman + Nginx + Affine 踩坑教程的更多相关文章

  1. virtualvenv+django+uWSGI+nginx 部署 踩坑记录

    原创博文 转载请注明出处! uwsgi: unrecognized option '--http:8089' uwsgi: unrecognized option '--http' uwsgi trk ...

  2. Nginx的踩坑实录

    1.昨天在为一个新项目配置地址转发,搞了很久都没生效,日志也没有问题,但就是没到转发的目标机器上. nginx.conf 配置如下: location /prism{ proxy_pass http: ...

  3. python爬虫踩坑教程

    我们的目标是爬取下面这个个网址上的2010~2018年的数据 http://stockdata.stock.hexun.com/zrbg/Plate.aspx?date=2015-12-31 获取我们 ...

  4. Linux下pcstat安装踩坑教程

    首先安装golang 1.进入官方链接下载对应自己系统版本的Golang安装包:https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz root@ub ...

  5. nginx搭建网站踩坑经历

    为了更好的阅读体验,请访问我的个人博客 前言 早上刷抖音刷到一个只需要三步的nginx搭建教程(视频地址),觉得有些离谱,跟着复现了一遍,果然很多地方不严谨并且省略了大量步骤,对于很多不了解linux ...

  6. MySQL 5.7版本安装教程-踩坑总结

    下载 MySQL下载地址 选择下载64位(看自己电脑是32位还是64位) 点击下载之后,它会让你登录,没有Oracle账户,跟着它的步骤注册一个就好了. 安装 打开下载好的压缩包解压到你的某一目录下, ...

  7. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  8. 在CentOS/Windows下配置Nginx(以及踩坑)

    在CentOS/Windows下配置Nginx(以及踩坑) 1. 序言 因为这类文章网上比较多,实际操作起来也大同小异,所以我并不会着重于详细配置方面,而是将我配置时踩的坑写出来. 2. CentOS ...

  9. nginx + gunicorn + django 2.0 踩坑

    部署踩坑 部署踩坑提前准备服务器端准备安装nginx使用uwsgi部署使用gunicorn配置配置nginx配置django中的路径url 提前准备 在本地能够 python(3) manage.py ...

  10. Docker 部署 redis教程,附带部分小建议,防止踩坑

    Docker 部署 redis,附带部分小建议,防止踩坑 跟所有人一样,我们先从docker基本命令开始 一.拉取redis镜像(配图来自菜鸟,其实截图没多大意义,对比看下) # 默认就拉取laste ...

随机推荐

  1. tomcat-shell脚本

    自动部署项目脚本参考: #!/bin/bash#自动部署脚本source /etc/profileexport LANG=zh_CN.UTF-8#tomcat路径tomcatBinPath=/usr/ ...

  2. 关于Bevy中的原型Archetypes

    认识Bevy中的原型 Bevy是基于ECS(Entity-Component-System)架构的游戏引擎,其中的Entity实体是游戏中的一个基本对象,但实体本身通常只是一个标识id,它不包含任何具 ...

  3. 【MOOC】华中科技大学计算机组成原理慕课答案-第八章-输入输出系统

    应一个同学后台留言,说让我发就发全,那我干脆把剩的这一章测验也发了吧. 以下解析由GPT生成,不保证可读可解释,仅保证答案正确. 单选 1 (单选(2分)) ‎某中断系统中,每抽取一个输入数据就要中断 ...

  4. 决策单调性DP

    决策单调性DP是一个非常重要的DP类别.在决策点随枚举点增加单调不降时,可以有效地优化复杂度. 一般而言,决策点指的是对于一个 \(f[i]\),它的值需要从另一个值j中转移,而对于所有j,令 \(f ...

  5. 智表ZCELL产品V2.0发版小感

    不知不觉,智表从诞生以来已经两年多了,首先感谢各位用户的支持,没有大家的支持,智表这个产品估计早就已经终止了,正是大家的支持和鼓励,智表才一步一步走到了今天.智表最初是从一个简单不能再简单的table ...

  6. ESP32S3 OTA升级

    ESP32S3 OTA升级 学习自b站视频[ESP-IDF-OTA远程升级简单介绍-宋工]https://www.bilibili.com/video/BV1X1zbYGEix?vd_source=a ...

  7. OpenPPL的执行流程与类间关系UML表达

    上一讲,对OpenPPL进行了介绍,以及通过官方文档,学习了它的python与C++的操作流程,以及如添加新的引擎与Op算子. 本节,将通过阅读代码通过UML梳理操作流程以及类之间的相互关系 src地 ...

  8. 在MySQL数据库中保存布尔型数据

       在存储数据时,经常会用到"是"."否"或者"有"."无"这种数据,这种时候就要应用布尔型这种数据类型了.那如何在M ...

  9. MySQL-Canal-Kafka数据复制详解

    摘要 MySQL被广泛用于海量业务的存储数据库,在大数据时代,我们亟需对其中的海量数据进行分析,但在MySQL之上进行大数据分析显然是不现实的,这会影响业务系统的运行稳定.如果我们要实时地分析这些数据 ...

  10. 解决Vmware使用中的卡顿问题

    打开首选项到内存,将其修改为图中的设置 打开优先级,设置如图 打开对应虚拟机设置,如图做两步设置 全部设置完成后,再次打开虚拟机使用发现完全不卡了!