chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

ローカルLLM用Dockerfile清書

課題:ローカルLLMを試してきて、だいたいモデルとパラメータが決まってきた。試行錯誤のため手作業でコマンド起動していたけどメモ書きレベルで再現性があやうい。起動時のパラメータ類を固定化するためDockerファイルを清書して仕上げたい
取り組み:Claudeに聞きながら最終版のDockerfileを作る
結果: ファイル一式作成、イメージのビルドと言語モデル(Qwen)のDL、Webサービス起動まで確認

詳細:
Claudeと相談するとdocker-composeがいいかと思い、Qwen用のDockerfile一式は以下とした。
言語モデルはサイズがでかいのでコンテナ内には置かずコンテナ外(ホストOS側と言うのか)に配置、LLM用実行ファイル一式はコンテナ内。

file: docker-compose.yml

services:
  llm:
    build: .
    image: local-llm-llama:20260430
    volumes:
      - ./models:/app/models
    command: >
      --host 0.0.0.0
      --port 8080
      -c 4048
      -ngl 0
      --temp 0.2
      --threads 8
      --batch-size 256
      --ubatch-size 64
      --mlock
      --no-mmap
    ports:
      - "8080:8080"

file: Dockerfile

FROM ubuntu:22.04

# install build tools
RUN apt-get update && apt-get install -y \
    git build-essential cmake wget curl \
    gcc-12 g++-12 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

ENV CC=gcc-12
ENV CXX=g++-12

# clone llama.cpp  and build
RUN git clone https://github.com/ggerganov/llama.cpp.git && \
    cd llama.cpp && \
    mkdir build && \
    cd build && \
    cmake .. && \
    make -j

# setup execute envirnment
COPY entrypoint.sh  /app/entrypoint.sh
RUN chmod +x   /app/entrypoint.sh

ENTRYPOINT ["/app/entrypoint.sh"]

file: entrypoint.sh

#!/bin/bash
# entrypoint.sh

MODEL_DIR="/app/models"
MODEL_FILE='Qwen2.5-7B-Instruct-Q4_K_M.gguf'
MODEL_URL='https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q4_K_M.gguf'

# create models dir if not exists
if [ ! -d "$MODEL_DIR" ]; then
    echo "Creating $MODEL_DIR..."
    mkdir -p "$MODEL_DIR"
fi

# dl gguf file if not exists
if [ ! -f "$MODEL_FILE" ]; then
    echo "Downloading Qwen2.5 GGUF..."
    wget -O "$MODEL_FILE" "$MODEL_URL"
else
    echo "Model already exists, skipping download."
fi

# start llama-server
exec /app/llama.cpp/build/bin/llama-server --model "$MODEL_FILE" "$@"

以下でビルドと起動する

docker compose up

8080でListen しているので他のPCからアクセス可能

■追記
言語モデルの指定と、コマンド起動時のパラメータがdocker-compose.yml、entrypoint.shに分かれてしまって情報の集約性の観点で問題かと思えた。Claudeと相談して、.envファイルに集約することにした (まだ、すべてのパラメータが集約できている状況ではないですが・・)
file: .env (環境設定ファイル)

#!/bin/sh

MODEL_FILE='Qwen2.5-7B-Instruct-Q4_K_M.gguf'
MODEL_URL='https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q4_K_M.gguf'

CONTEXT_SIZE=2048
SERVICE_PORT=8080
N_OF_THREADS=4
#  Model name: Intel(R) Core(TM) i5-3570K CPU @ 3.40GHz

file: docker-compose.yml

services:
  llm:
    build: .
    image: local-llm-llama:20260430
    env_file: .env
    volumes:
      - ./models:/app/models
    command: >
      --host 0.0.0.0
      --port $SERVICE_PORT
      --ctx-size $CONTEXT_SIZE
      --threads $N_OF_THREADS
      --n-gpu-layers 0
      --temp 0.2
      --batch-size 256
      --ubatch-size 64
      --parallel 1
      --mlock
    ports:
      - "${SERVICE_PORT}:${SERVICE_PORT}"

file: Dockerfile

FROM ubuntu:22.04

# install build tools
RUN apt-get update && apt-get install -y \
    git build-essential cmake wget curl \
    gcc-12 g++-12 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

ENV CC=gcc-12
ENV CXX=g++-12

# clone llama.cpp  and build
RUN git clone https://github.com/ggerganov/llama.cpp.git && \
    cd llama.cpp && \
    mkdir build && \
    cd build && \
    cmake .. && \
    make -j

# setup execute envirnment
COPY entrypoint.sh  /app/entrypoint.sh
RUN chmod +x   /app/entrypoint.sh

ENTRYPOINT ["/app/entrypoint.sh"]

file: entrypoint.sh

#!/bin/sh
# entrypoint.sh

MODEL_DIR="/app/models"
MODEL_FILE="${MODEL_FILE:-Qwen2.5-7B-Instruct-Q4_K_M.gguf}"
MODEL_URL="${MODEL_URL:-https://huggingface.co/bartowski/Qwen2.5-7B-Instruct-GGUF/resolve/main/Qwen2.5-7B-Instruct-Q4_K_M.gguf}"
MODEL_PATH="$MODEL_DIR/$MODEL_FILE"

# create models dir if not exists
echo "check models dir"
if [ ! -d "$MODEL_DIR" ]; then
    echo "Creating $MODEL_DIR..."
    mkdir -p "$MODEL_DIR"
fi

# dl gguf file if not exists
echo "check LLM models"
if [ ! -f "$MODEL_PATH" ]; then
    echo "Downloading Qwen2.5 GGUF..."
    wget -q -O "$MODEL_PATH" "$MODEL_URL"
else
    echo "Model already exists, skipping download."
fi

# start llama-server
#
exec /app/llama.cpp/build/bin/llama-server --model "$MODEL_PATH" "$@"

■メモ
Phi-3.5-mini-instruct-Q4_K_M.ggufを使って作曲について質問してみた。言語モデルの規模は3.8B相当らしい

いまはちょっと休止中だけど、作曲Agentを作ってAgentと対話しながら、NOTEをAbletonLiveに書き込んだりして欲しい
Phi-3.5用 .env(抜粋)

MODEL_FILE=Phi-3.5-mini-instruct-Q4_K_M.gguf
MODEL_URL=https://huggingface.co/bartowski/Phi-3.5-mini-instruct-GGUF/resolve/main/Phi-3.5-mini-instruct-Q4_K_M.gguf
SERVICE_PORT=8080
CONTEXT_SIZE=4096
N_OF_THREADS=4

Phi-3.5用docker-compose.yml 

services:
  llm:
    build: .
    image: local-llm-llama:20260430
    env_file: .env
    volumes:
      - ./models:/app/models
    command: >
      --host 0.0.0.0
      --port $SERVICE_PORT
      --ctx-size $CONTEXT_SIZE
      --n-gpu-layers 0
      --threads $N_OF_THREADS
      --temp 0.2
      --top-p 0.9
      --top-k 40
      --predict 512
      --repeat-penalty 1.1
      --batch-size 512
      --ubatch-size 128
      --mlock
      --parallel 2
    ports:
      - "${SERVICE_PORT}:${SERVICE_PORT}"