TeamCity сервер + Nginx в докер контейнерах на Ubuntu 20

  DevOps

Для реализации данной идеи рекомендую взять сервер c хотя бы 4Гб оперативки. В противном случае контейнер с TeamCity будет очень долго стартовать и мы нередко будем видеть в логах ООМ.
Я буду использовать Ubuntu 20.
Для начала установим докер по инструкции с офф сайта.

sudo apt-get update && apt-get upgrade –y
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo docker run hello-world # test

Теперь создадим папки, где Тимсити будет хранить логи и данные:

mkdir -p /var/teamcity/datadir /var/teamcity/logs
chown -R 1000:1000 /var/teamcity/datadir /var/teamcity/logs

Для проверки можно запустить сервер командой:

docker run  -d --rm --name teamcity-server-instance –v /var/teamcity/datadir:/data/teamcity_server/datadir -v /var/teamcity/logs:/opt/teamcity/logs -p 80:8111 jetbrains/teamcity-server

Но я предлагаю сразу сделать systemd unit. Запишем в файл /etc/systemd/system/teamcity.service

[Unit]
Description=teamcity
After=network.target

[Service]
ExecStart=docker run --rm --name teamcity-server-instance \
-v /var/teamcity/datadir:/data/teamcity_server/datadir \
-v /var/teamcity/logs:/opt/teamcity/logs \
-p 8111:8111 \
jetbrains/teamcity-server
Restart=always

[Install]
WantedBy=multi-user.target

Готово. Запускаем.

systemctl daemon-reload
systemctl enable teamcity
systemctl start teamcity

Можно посмотреть логи контейнера и убедиться что все в порядке.

docker logs teamcity-server-instance

Мы должны увидеть последней строкой лога следующее:

Startup confirmation is required. Open TeamCity web page in the browser. Server is running at http://localhost:8111

Идём адресу сервера. Например, teamcity.amulin.ru:8111 .

Первый запуск TeamCity

Работает, но ещё не все. Хочется иметь перед teamcity nginx с блекджеком и сертификатом.

Создадим самоподписанный сертификат и положим его в папку /etc/ssl/teamcity.amulin.ru

mkdir -p /etc/ssl/teamcity.amulin.ru
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -keyout /etc/ssl/teamcity.amulin.ru/mykey.key -out /etc/ssl/teamcity.amulin.ru/cert.crt

Сделаем конфиг для nginx, который направит трафик на нужный контейнер. Для этого создадим папку /etc/nginx/conf.d и файл /etc/nginx/conf.d/teamcity.amulin.ru.conf следующего содержания:

    server {
        listen 443 ssl;
        listen [::]:443 ssl ipv6only=on;
        server_name teamcity.amulin.ru;

        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://teamcity-server-instance:8111;
        }

        ssl_certificate /etc/ssl/teamcity.amulin.ru/cert.crt;
        ssl_certificate_key /etc/ssl/teamcity.amulin.ru/mykey.key;
    }

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name teamcity.amulin.ru;

        if ($host = teamcity.amulin.ru) {
            return 301 https://$host$request_uri;
        }
    }

Здесь я использую прокси на http://teamcity-server-instance:8111; teamcity-server-instance – это имя контейнера. Далее нам нужно будет прилинковать его к контейнеру nginx.

Теперь сделаем systemd unit под nginx /etc/systemd/system/nginx.service

[Unit]
Description=nginx

[Service]
ExecStart=docker run --rm --name nginx \
-v /etc/nginx/conf.d/teamcity.amulin.ru.conf:/etc/nginx/conf.d/default.conf \
-v /etc/ssl/teamcity.amulin.ru:/etc/ssl/teamcity.amulin.ru:ro \
-p 80:80 \
-p 443:443 \
--link teamcity-server-instance \
nginx
Restart=always

[Install]
WantedBy=multi-user.target

Как раз —link teamcity-server-instance даём nginx возможность сходить в контейнер TeamCity.

Запускаем

systemctl daemon-reload
systemctl enable nginx
systemctl start nginx

И даже не удивляемся, что все работает. Конечно браузер предупредит, что сертификат самоподписанный, но мы можем пойти на такой риск.

Загрузка TeamCity уже за nginx.

Теперь настраиваем БД и ждём.

Выбор типа базы данных при первом запуске TeamCity

И наконец лицензионное соглашение и создание админа, где мы конечно же укажем логин — admin, а пароль 12345678.

Очень хочется, чтобы после перезагрузки все само поднялось. Попробуем перезапустить машину и убедимся что все работает. Магия!

docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED              STATUS              PORTS                                                                      NAMES
8c2d1962cb47   nginx                       "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   nginx
58bb3068be4f   jetbrains/teamcity-server   "/run-services.sh"       About a minute ago   Up About a minute   0.0.0.0:8111->8111/tcp, :::8111->8111/tcp                                  teamcity-server-instance