【vultr×Dify】でプライベートなAI環境構築

## 参考記事
今回参考にさせていただいた有益な記事は以下。
- [Difyを使ってLLMアプリを開発しよう - 環境構築とインターネット公開](https://note.com/xoihazard/n/nf1699039c73b#f726e3f2-c86e-4e35-92f4-2da7df78b955)

- [公式 Docker Compose デプロイ](https://docs.dify.ai/ja-jp/getting-started/install-self-hosted/docker-compose)

## 前提
- vultr(ヴァルチャー？)でVPSを契約している。
- vultrサーバーのSSHの設定を済ませている。

## 環境
vultr：ubuntu 24.0.0 LTS


## Dockerを使えるようにする
```zsh
sudo apt update

sudo apt install -y docker.io

sudo systemctl start docker

sudo systemctl enable docker

sudo apt install -y curl

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

sudo docker --version

sudo docker-compose --version
```


## Dify構築

```zsh
mkdir services
```

Difyのソースコードをローカルにクローンします
```zsh
git clone https://github.com/langgenius/dify.git
```

基本的には以下の公式の手順を参考に進めていきます。
ちょっとだけ変えないとうまく動かないという感じ。
https://docs.dify.ai/ja-jp/getting-started/install-self-hosted/docker-compose#difyno

### Difyの起動
1. difyソースコードのdockerディレクトリに移動し、次のコマンドを実行してdifyを起動する
```zsh
cd service/dify/docker
```

2. docker-compose.override.yamlのオーバーライド

`dify/docker`ディレクトリに`docker-compose.override.yaml`を作成する。
内容は以下の通り。
```
services:
  api:
    environment:
      CONSOLE_WEB_URL: 'http://localhost:8080'
      CONSOLE_API_URL: 'http://vultrのパブリックIP'
      MAIL_TYPE: 'smtp'
      MAIL_DEFAULT_SEND_FROM: 'hoge@gmail.com'
      SMTP_SERVER: 'smtp.gmail.com'
      SMTP_PORT: 587
      SMTP_USERNAME: 'hoge@gmail.com'
      SMTP_PASSWORD: 'hogepass' # Gmailのアプリパスワード
      SMTP_USE_TLS: 'true'
  worker:
    environment:
      CONSOLE_WEB_URL: 'http://localhost:8080'
      CONSOLE_API_URL: 'http://vultrのパブリックIP'
      MAIL_TYPE: 'smtp'
      MAIL_DEFAULT_SEND_FROM: 'hoge@gmail.com'
      SMTP_SERVER: 'smtp.gmail.com'
      SMTP_PORT: 587
      SMTP_USERNAME: 'hoge@gmail.com'
      SMTP_PASSWORD: 'hogepass'
      SMTP_USE_TLS: 'true'
  nginx:
    ports:
      - "8080:80" # Difyを公開するポート
```

3. 環境ファイルをコピーする
dify/api/.env
dify/web/.env
dify/docker/.env
の3つがあるので、それぞれ以下のコマンドでコピーしておく。
```zsh
    cp .env.example .env
```
この時`dify/dokcer/.env`の中身は以下の2点を書き換える。
- apiのパス
- database(任意)

apiのパスはvultrのパブリックIPを明示的に記述しておく。
```.env
CONSOLE_API_URL=http://vultrのパブリックIP
CONSOLE_WEB_URL=http://vultrのパブリックIP
SERVICE_API_URL=http://vultrのパブリックIP
```

databaseは任意で使いたいpostgresがあればその情報に書き換える。
```.env
DB_USERNAME=mydbuser
DB_PASSWORD=mydbpass
DB_HOST=mydbhost
DB_PORT=5432
DB_DATABASE=mydb
```

Difyの公式が作ってくれてる図は以下。
![](https://storage.googleapis.com/zenn-user-upload/864ae81df2c2-20241016.png)

Docker内のnginxが吸収してくれていることによって、コンテナ間のネットワークはすべてDocker環境の中に閉じ込められている。
つまり、使う人はローカルでDocker環境を立ち上げるだけでよく、外部からは`localhost`（デフォルトである`80番）だけ意識すればいいような作りになっている。（美しい、かっけぇ...）

なので今回のvultr環境では、
dockerのlocalhost:8080→
vultr(ホスト)の80番→
パブリックのIP(インターネット)といった具合に繋がっている。

上記で述べた「apiのパスはvultrのパブリックIPを明示的に記述しておく」というのもこれによるもの。


4. Docker コンテナを起動する
```
docker-compose up -d
```

4. 確認する
```
docker compose ps
```

### Dockerをsudoなしで使えるようにする
```
sudo usermod -aG docker $USER

newgrp docker
```

### nginxの502エラーが出る場合
以下のコマンドを実行して、それぞれのコンテナのIPを確認する
```zsh
docker ps -q | xargs -n 1 docker inspect --format '{{ .Name }}: {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
```

`dify/docker/nginx/conf.d/default.conf`を編集して上記コマンドで確認したIPを明示的に指定する。

詳しくは公式のリファレンスに記載がある。
https://docs.dify.ai/ja-jp/learn-more/faq/install-faq


## firewallの設定を忘れずに
とりあえずdifyが使える状態になったので、AIに与えた情報が流出するかもとか気にせずに好きに使えます。
自分アプリに連携するなり想像が広がりますね。
あとはvultr側でのfirewallとかの設定を忘れないように気をつけてくださいね。