TS-Server

Сервер TeamSpeak в Docker: установка и настройка

Установка сервера TeamSpeak 3 в Docker по официальному образу — docker-compose с разбором каждой строки, тома, бэкап, обновление и TeamSpeak 6 в контейнере.

Проверено 13 августа 2026. Официальный образ teamspeak (тег 3.13.8, переменные окружения, том /var/ts3server) сверен с Docker Hub и репозиторием TeamSpeak-Systems; конфигурация TeamSpeak 6 Server — с github.com/teamspeak/teamspeak6-server (CONFIG.md и compose-примеры), статус — beta. Проверено 7 августа 2026 года.

TeamSpeak в контейнере — это официальный образ, один compose-файл и сервер, который поднимается за минуту на любой машине с Docker. Эта инструкция проведёт от установки Docker до работающего сервера с томами, бэкапом и обновлением без потери данных — и отдельно разберёт грабли с портом 30033, из-за которых в контейнерных установках не работает передача файлов.

Сначала честный вопрос: а нужен ли вам Docker вообще?

Docker оправдан, когда на сервере уже крутятся другие контейнеры и TeamSpeak встраивается в общий docker-compose; когда нужно несколько изолированных экземпляров на одной машине; когда важно разворачивать окружение одной командой из файла в git. Контейнер фиксирует версию, не мусорит в систему и сносится бесследно.

Docker избыточен, если у вас один выделенный VDS под один голосовой сервер. TeamSpeak — статический бинарник без зависимостей: ему не нужна изоляция библиотек, ради которой обычно и берут контейнеры. Docker здесь добавляет слой абстракции, сетевой NAT и новые точки отказа, а взамен даёт немногое. Если вы выбираете способ запуска с нуля, сравните его с Ubuntu и Windows в обзоре создания сервера TeamSpeak. Для одного VDS быстрее и надёжнее обычная установка на Ubuntu — с systemd и без прослоек.

Если решили в пользу Docker — поехали. Понадобится VDS с Ubuntu 24.04 или 26.04, root-доступ и 15 минут. Для нового VDS выбирайте 26.04, а перед миграцией существующего сервера сверяйтесь с разбором Ubuntu 24.04 и 26.04. Подготовка машины и обновление пакетов описаны в инструкции по Ubuntu, в первом шаге.

Устанавливаем Docker и Compose

На Ubuntu 24.04 всё нужное есть в штатных репозиториях:

apt update
apt install -y docker.io docker-compose-v2

Проверяем, что демон запущен и отвечает:

docker version

В выводе должны быть блоки Client и Server. Если хотите самые свежие версии Docker — ставьте из официального репозитория Docker по инструкции с docs.docker.com, но для TeamSpeak возможностей штатного пакета хватает с запасом.

Пишем docker-compose.yml

Создаём каталог проекта и конфиг:

mkdir -p /opt/teamspeak-docker && cd /opt/teamspeak-docker

Файл /opt/teamspeak-docker/docker-compose.yml:

services:
  teamspeak:
    # Официальный образ с Docker Hub. Тег фиксируем на конкретной
    # версии, а не latest: обновление сервера должно быть осознанным
    # действием, а не сюрпризом при пересоздании контейнера.
    image: teamspeak:3.13.8

    # Имя контейнера, чтобы в командах писать teamspeak,
    # а не сгенерированное teamspeak-docker-teamspeak-1.
    container_name: teamspeak

    # Автозапуск: контейнер поднимается после перезагрузки VDS
    # и после падения процесса. Аналог systemd-юнита с Restart=.
    restart: unless-stopped

    ports:
      # Голос. Обязательно /udp — по TCP клиенты не подключатся.
      - "9987:9987/udp"
      # Передача файлов, аватарки, иконки. СТРОГО один в один —
      # почему, разобрано в следующем шаге.
      - "30033:30033"
      # ServerQuery (10011/tcp) наружу НЕ публикуем: это полный
      # админ-доступ с нешифрованным паролем. Нет строки — нет порта.

    environment:
      # Без принятия лицензии сервер не стартует и завершится
      # с ошибкой в логе. Значение view вместо accept печатает
      # текст соглашения.
      TS3SERVER_LICENSE: accept

    volumes:
      # Всё состояние сервера — база, файлы, логи — живёт
      # в /var/ts3server внутри контейнера. Монтируем наружу,
      # иначе данные умрут вместе с контейнером.
      - ./ts3data:/var/ts3server

Здесь использован bind mount (./ts3data) — каталог рядом с compose-файлом. Данные видны обычными командами, их просто бэкапить. Альтернатива — именованный том (ts3data: плюс секция volumes: в конце файла): им управляет Docker, и с правами доступа проблем меньше — об этом в шаге про грабли.

Пробрасываем порт 30033 один в один

Это самый важный шаг статьи, и почти ни одна инструкция его не объясняет.

С голосовым портом 9987 можно делать что угодно: опубликуйте его наружу как 9988 ("9988:9987/udp") — и клиенты, подключаясь на адрес:9988, будут прекрасно работать. С портом передачи файлов 30033 этот фокус не пройдёт: файлы, аватарки и иконки молча перестанут ходить, а голос при этом останется в порядке — поэтому проблему замечают не сразу и ищут не там.

Причина в устройстве протокола. Передача файлов в TeamSpeak идёт не через голосовое соединение, а через отдельное TCP-подключение. Когда клиент запрашивает файл, сервер отвечает служебным сообщением: ключ передачи и номер порта, на котором слушает он сам — тот, что задан в его конфигурации, по умолчанию 30033. Клиент открывает новое TCP-соединение на этот порт по адресу сервера.

Теперь смотрите, что происходит при кривом пробросе "30044:30033". Внутри контейнера сервер слушает 30033 и честно называет клиенту порт 30033. Клиент подключается на внешний-адрес:30033 — а там ничего нет: снаружи Docker опубликовал 30044, о котором сервер не знает. Соединение отваливается, файлы не ходят.

Отсюда правило: внешний и внутренний номер порта передачи файлов обязаны совпадать. Либо стандартно:

    ports:
      - "30033:30033"

Либо, если 30033 на хосте занят, меняем порт и внутри контейнера тоже — переменной окружения, которую entrypoint официального образа превращает в параметр filetransfer_port конфига:

    ports:
      - "30044:30044"
    environment:
      TS3SERVER_LICENSE: accept
      TS3SERVER_FILETRANSFER_PORT: "30044"

Тогда сервер и слушает 30044, и называет клиенту 30044 — всё сходится. Полная карта портов TeamSpeak с назначением каждого — в справочнике по портам.

Запускаем сервер и сохраняем ключи

Поднимаем:

docker compose up -d

Docker скачает образ и запустит контейнер. Теперь — не откладывая — смотрим лог первого запуска:

docker logs teamspeak

В нём будет блок I M P O R T A N T с тремя строками: loginname= "serveradmin", password= "..." и ниже — token=.... Пароль — это админ-доступ к ServerQuery, token — privilege key, дающий права администратора первому, кто введёт его в клиенте (Permissions → Use Privilege Key).

Сохраните обе строки сейчас. В контейнерной установке это критичнее, чем в обычной: docker logs привязан к конкретному контейнеру. Поменяете compose-файл, выполните docker compose up -d — Docker пересоздаст контейнер, и лог первого запуска исчезнет вместе с токеном. Подстраховка: копия лога попадает и в файлы внутри тома, grep -r "token=" ./ts3data/logs/ найдёт ключ, пока логи не ротировались. Если и ключ использован, и доступ потерян — инструкция по восстановлению работает и для контейнера: ServerQuery доступен изнутри, например docker exec -it teamspeak sh, а дальше как обычно.

Проверяем снаружи, а не по логу: подключитесь клиентом на IP сервера, активируйте privilege key и загрузите аватарку — она проверяет как раз порт 30033.

Настраиваем бэкап

Что копировать — то же, что и без Docker: база ts3server.sqlitedb, каталог files/, файлы конфигурации. Разница в том, что всё это уже собрано в одном месте — томе ./ts3data. Не нужно вспоминать пути: бэкап тома — это бэкап сервера целиком.

Второе отличие: останавливаем не systemd-сервис, а контейнер. Пропускать остановку нельзя — SQLite-базу, в которую сервер пишет, копировать на живую опасно: в архив попадёт несогласованный файл. Скрипт /opt/teamspeak-docker/backup.sh:

#!/bin/bash
set -euo pipefail

BACKUP_DIR=/var/backups/teamspeak
STAMP=$(date +%F_%H-%M)

mkdir -p "$BACKUP_DIR"

cd /opt/teamspeak-docker
docker compose stop
tar czf "$BACKUP_DIR/ts3-docker-$STAMP.tar.gz" ts3data docker-compose.yml
docker compose start

find "$BACKUP_DIR" -name 'ts3-docker-*.tar.gz' -mtime +14 -delete
echo "OK: $BACKUP_DIR/ts3-docker-$STAMP.tar.gz"

В архив кладём и docker-compose.yml: вместе с томом он делает бэкап самодостаточным — на любой машине с Docker распаковали, docker compose up -d, сервер жив. Это одновременно и процедура переезда; подробно о переносе сервера со всеми настройками — в отдельной статье.

Скрипт — в cron на ночное время (chmod +x backup.sh, затем crontab -e), и раз в неделю забирайте архив на другую машину: бэкап на том же диске не переживёт смерть VDS.

Обновляем образ без потери данных

Ради этого шага том и выносили наружу. Контейнер — одноразовая обёртка вокруг данных: его можно убить и создать заново, и пока /var/ts3server смонтирован в том, сервер этого «не заметит».

Порядок обновления. Сначала бэкап (скрипт из предыдущего шага) — обновление базы необратимо, откат на старую версию сервера со свежей базой не поддерживается. Затем в docker-compose.yml меняем тег на новую версию — актуальный список тегов на странице образа teamspeak на Docker Hub, на 7 августа 2026 года свежий из них 3.13.8:

    image: teamspeak:3.13.8

И применяем:

docker compose pull
docker compose up -d

Docker скачает новый образ, остановит старый контейнер и создаст новый с тем же томом. Сервер при первом запуске сам мигрирует схему базы. Проверка — снаружи: клиент подключается, каналы и права на месте, аватарка загружается.

Именно поэтому в конфиге зафиксирован точный тег, а не latest: с latest та же команда pull притащила бы новую мажорную версию тогда, когда вы этого не планировали, — без бэкапа и без чтения changelog.

Пробуем TeamSpeak 6 в контейнере

У TeamSpeak 6 Server официальный способ установки — как раз Docker: образ teamspeaksystems/teamspeak6-server на Docker Hub, документация и примеры compose-файлов — в репозитории github.com/teamspeak/teamspeak6-server. Статус — beta: сервер не feature-complete, бета-лицензия даёт 32 слота и продлевается каждые два месяца, лицензии TeamSpeak 3 несовместимы, пути миграции с третьей версии нет. Что такое TeamSpeak 6 и чего от него ждать — в обзоре; здесь — только запуск.

Конфигурация устроена иначе, чем в TS3. Переменные окружения носят префикс TSSERVER_ (без тройки), лицензия принимается переменной TSSERVER_LICENSE_ACCEPTED=accept, данные живут в /var/tsserver, а вместо ts3server.ini — YAML-файл tsserver.yaml; любой параметр можно задать тремя равнозначными способами: аргументом командной строки, переменной окружения или строкой в YAML. Полный список — в CONFIG.md репозитория. Минимальный compose по мотивам официального примера:

services:
  teamspeak6:
    image: teamspeaksystems/teamspeak6-server:latest
    container_name: teamspeak6
    restart: unless-stopped
    ports:
      - "9987:9987/udp"    # голос
      - "30033:30033"      # передача файлов — правило "один в один" никуда не делось
      # - "10080:10080"    # WebQuery (HTTP API) — включается TSSERVER_QUERY_HTTP_ENABLED
      # - "10022:10022"    # ServerQuery по SSH — TSSERVER_QUERY_SSH_ENABLED
    environment:
      TSSERVER_LICENSE_ACCEPTED: accept
    volumes:
      - ./ts6data:/var/tsserver

Порты голоса и файлов те же, что у TS3, поэтому на одной машине два сервера одновременно потребуют разных внешних портов — и для файлового порта TS6 это значит менять его и внутри, переменной TSSERVER_FILE_TRANSFER_PORT. Классический ServerQuery на 10011 заменили HTTP- и SSH-варианты, по умолчанию выключенные. Privilege key при первом запуске так же печатается в docker logs teamspeak6 — правило «сохранить сразу» в силе.

Обходим типовые грабли

Права на каталог тома. Сервер внутри официального образа работает от пользователя ts3server с UID 9987, а не от root. Если bind mount указывает на каталог, куда UID 9987 писать не может, контейнер падает на старте с Permission denied в логе (классика — ошибка создания ts3server.ini или базы). Лечение: chown -R 9987:9987 /opt/teamspeak-docker/ts3data. Или сразу используйте именованный том — Docker выставит владельца сам при первом монтировании.

Потерянный privilege key. Уже разобрано в шаге про запуск, но повторим, потому что это грабли номер один: docker logs умирает вместе с контейнером, а контейнеры в Docker пересоздаются по любому чиху. Ключ и пароль serveradmin сохраняются в момент первого запуска, не «потом».

Логи. Смотреть их можно двумя способами, и они не дублируют друг друга полностью. docker logs -f teamspeak — stdout процесса: ошибки старта, принятие лицензии, учётные данные первого запуска. Файлы в ts3data/logs/ — содержательные логи самого сервера: подключения, баны, ошибки виртуальных серверов. При разборе проблемы «сервер не стартует» смотрите первый, «сервер работает странно» — вторые.

UDP и фаервол. Docker публикует порты в обход ufw — правила iptables от Docker срабатывают раньше. Из-за этого «закрытый» в ufw порт контейнера может оказаться открытым, и наоборот, включённый ufw не спасает, если вы случайно опубликовали 10011. Правило простое: что не должно торчать наружу — не публикуйте в ports: вовсе, это надёжнее любого фаервола перед контейнером.


Итог: контейнерный TeamSpeak — это compose-файл на двадцать строк, том с данными и три правила, которые не прощают нарушения: порт 30033 пробрасывается один в один, ключи первого запуска сохраняются немедленно, база живёт в томе с первого дня. Всё остальное — обычный уход: бэкап по cron, осознанное обновление тега и проверка восстановления хотя бы раз — до того, как оно понадобится по-настоящему.

Частые вопросы

Как установить сервер TeamSpeak в Docker?

Создайте docker-compose.yml с официальным образом teamspeak:3.13.8, примите лицензию, опубликуйте UDP 9987 и TCP 30033, а данные вынесите в постоянный том /var/ts3server. После запуска сохраните пароль serveradmin и privilege key из docker logs.

Почему в TeamSpeak на Docker не работают аватарки и передача файлов?

Почти всегда причина — порт 30033 проброшен не один в один. Порт для передачи файлов клиент узнаёт не из адреса подключения, а из ответа самого сервера: сервер называет тот порт, на котором слушает внутри контейнера. Если снаружи опубликован другой номер, клиент стучится в закрытую дверь. Решение: либо проброс 30033:30033, либо смена внутреннего порта переменной TS3SERVER_FILETRANSFER_PORT на тот же номер, что и снаружи.

Где взять privilege key, если TeamSpeak запущен в Docker?

Ключ и пароль serveradmin сервер печатает один раз при первом запуске — в контейнере они попадают в stdout, то есть в docker logs. Выполните docker logs teamspeak и найдите блок IMPORTANT со строками token= и password=. Учтите, что docker logs живут ровно столько, сколько контейнер — пересоздали его командой up после правки compose-файла, и лог первого запуска пропал вместе с ключом.

Потеряются ли данные при обновлении образа TeamSpeak?

Нет, если база и файлы лежат в томе, смонтированном в /var/ts3server. Контейнер — одноразовая обёртка, при docker compose pull и up -d он пересоздаётся из нового образа, а том остаётся на месте, и сервер мигрирует базу на новую версию сам. Если том не был подключён, данные жили внутри контейнера и погибли вместе с ним — поэтому том обязателен с самого первого запуска.

Можно ли запустить TeamSpeak 6 в Docker для боевого сервера?

Технически — да, официальный образ teamspeaksystems/teamspeak6-server публикуется на Docker Hub и заводится одним compose-файлом. Практически — рано. Сервер имеет статус beta, бета-лицензия ограничена 32 слотами и продлевается каждые два месяца, а пути миграции с TeamSpeak 3 нет. Для сообщества ставьте TeamSpeak 3, а шестую версию поднимайте рядом для экспериментов.

Docker или обычная установка — что выбрать для TeamSpeak?

Если у вас один VDS под один голосовой сервер — ставьте обычным способом: слоёв меньше, граблей меньше, а выигрыша от контейнера почти нет. Docker оправдан, когда на машине уже живут другие контейнеры, когда нужно несколько изолированных серверов или когда важно поднимать окружение одной командой из конфига.

Что почитать дальше