Ollama + Open-WebUIを完全スタンドアロンでセットアップしてみた

# 動機

ローカルLLMを使用したい人の中には、ネットワークから完全に切り離された環境で使いたいという人もいるだろうなと思ったので。

# 前提条件

- オンライン環境で稼働しているdocker環境

# 事前準備

作業用Linux環境でいろいろと必要なファイルを作ったりダウンロードしたりする。

## `docker pull`で各イメージを入手

```bash
$ docker pull ollama/ollama:latest
$ docker pull ghcr.io/open-webui/open-webui:main
```

## 入手したイメージを`docker save`でファイルに保存する

```bash
$ docker save ollama/ollama:latest | gzip > ollama.tar.gz
$ docker save ghcr.io/open-webui/open-webui:main | gzip > open-webui.tar.gz
```

## dockerの実行ファイルを入手する

以下のURLから最新の`docker-x.x.x.tgz`をダウンロードする
https://download.docker.com/linux/static/stable/x86_64/

## docker-composeの実行ファイルを入手する

以下のURL(GitHub)から実行ファイルをダウンロードする
https://github.com/docker/compose/releases

## Ollamaで稼働させたいModelをダウンロードする

### 稼働させたいGGUFをダウンロードする
※今回はELYZAを使用しました。
https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/tree/main

### ダウンロードしたファイルに合わせてModelfileを作成し、GGUFと同じ場所に置く

```text:Modelfile
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
TEMPLATE """{{ if .System }}
system


{{ .System }}
{{ end }}{{ if .Prompt }}
user


{{ .Prompt }}
{{ end }}
assistant


{{ .Response }}
"""
PARAMETER stop "
"
PARAMETER stop "
"
PARAMETER stop "
"
PARAMETER stop "<|reserved_special_token"
```

# インストール

以下手順を展開先の実機で作業する。

## iptablesのインストール（debianのセットアップDVDに含まれている）

```bash
# apt install iptables
```

## dockerグループを追加し、作業ユーザを参加させる

```bash
# groupadd docker
# usermod -aG docker $USER
```

## docker本体のインストール

```bash
# tar xzvf docker-x.x.x.tgz
# cp docker/* /usr/bin/
```

## docker本体とdockerのLinuxソケットをsystemdに登録

```unit-file:/usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target
Wants=network-online.target
Requires=docker.socket

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target
```

```unit-file:/usr/lib/systemd/system/docker.socket
[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
```

## dockerを起動し、自動起動するよう設定する

```bash
# systemctl daemon-reload
# systemctl start docker.service
# systemctl enable docker.service
```

## dockerイメージをインポートする

```bash
# docker load < ollama.tar.gz
# docker load < open-webui.tar.gz
```

## docker-composeのインストール

この時点でコンテナを立ち上げる準備は完了しているが、管理を楽にするために
docker-composeをセットアップしておく。

```bash
# cp docker-compose /usr/local/bin/
# chmod +x /usr/local/bin/docker-compose
```

## docker-composeで管理する用のフォルダを作成する

まあ、どこでもいいです。

```bash
# mkdir /opt/ollama
# cd /opt/ollama
```

## docker-compose.ymlを作成する

```yml:/opt/ollama/docker-compose.yml
services:
  ollama:
    image: ollama/ollama
    container_name: ollama
    volumes:
      - ollama:/root/.ollama
      - ./model:/root/model
    ports:
      - "11434:11434"
    restart: unless-stopped
# GPUを利用する場合、ここのコメントを外す
#    deploy:
#      resources:
#        reservations:
#          devices:
#          - driver: nvidia
#            capabilities: ["gpu"]
#            count: all

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    ports:
      - "3000:8080"
    volumes:
      - open-webui:/app/backend/data
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: always

volumes:
  ollama:
  open-webui:
```

## コンテナを起動する

```bash
# docker-compose up -d
```

## OllamaコンテナにModelファイルをインポートする

### docker-compose.ymlのあるフォルダに`model`フォルダができているので、そこにGGUFとModelfileを格納する。

```bash:/opt/ollama/model/
# ls
Llama-3-ELYZA-JP-8B-q4_k_m.gguf Modelfile
```

### コンテナの中に入る

```bash
# docker-compose exec ollama bash
#
```

### GGUFをインポートする

```bash
# cd ~/model
# ollama create elyza:jp8b -f ModelFile
```

### コンテナから出る

```bash
# exit
```

以上でセットアップは終了。

# 動作確認

`http://localhost:3000` でOpen-WebUIにアクセスできる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298004/d5c3b6af-25d5-e631-0bc1-c144b1dc9d07.png)

# おまけ

一連のファイルをISOファイルにしておくとVMに入れるときとかに便利です。

```bash
# mkisofs -r -J -V ollama -allow-limited-size -o ollama-standalone.iso ollama
```