В рамках текущего проекта нам необходимо реализовать CI для выливки приложений, а так-как мы решили не использовать GitLab (для наших задач это большой оверхэд) и используем Gitea то естественно возник вопрос что использовать для сборки и доставки приложений. Решено было использовать Concourse CI.
Concourse CI — это современный инструмент непрерывной интеграции и доставки (CI/CD) с декларативным описанием пайплайнов, ориентированный на простоту, прозрачность и масштабируемость.
Установка Concourse CI
Установку будем проводить при помощи Docker Compose и нам естественно понадобится установленный на хоста Docker и Docker Compose и установим их по инструкции «Установка Docker+DockerCompose+KubeCtl+Helm» .
Загружаем docker-compose окружение с официального GitHub-репозитария.
# cd /opt/
# git clone https://github.com/concourse/concourse-docker.git
Генерируем ключи.
# cd ./keys/
# ./generate
Редактируем конфигурацию docker-compose.yml. Установим имя пользователя, пароль и внешний URL и при необходимости меняем настройки создания базы данных.
version: '3'
services:
db:
image: postgres:16
environment:
POSTGRES_DB: concourse
POSTGRES_USER: concourse_user
POSTGRES_PASSWORD: concourse_pass
volumes:
- ./postgres_data/:/var/lib/postgresql/data/
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
web:
image: concourse/concourse
command: web
links: [db]
depends_on: [db]
ports: ["8080:8080"]
volumes: ["./keys/web:/concourse-keys"]
environment:
CONCOURSE_EXTERNAL_URL: https://concourse.interlan.xyz
CONCOURSE_POSTGRES_HOST: db
CONCOURSE_POSTGRES_USER: concourse_user
CONCOURSE_POSTGRES_PASSWORD: concourse_pass
CONCOURSE_POSTGRES_DATABASE: concourse
CONCOURSE_ADD_LOCAL_USER: administrator:Q7ug32G2
CONCOURSE_MAIN_TEAM_LOCAL_USER: administrator
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
worker:
image: concourse/concourse
command: worker
privileged: true
depends_on: [web]
volumes: ["./keys/worker:/concourse-keys"]
links: [web]
stop_signal: SIGUSR2
environment:
CONCOURSE_TSA_HOST: web:2222
# enable DNS proxy to support Docker's 127.x.x.x DNS server
CONCOURSE_GARDEN_DNS_PROXY_ENABLE: "true"
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
Запускаем Docker Compose.
# docker-compose up -d
Работа с утилитой Fly
Авторизуемся в Web-интерфейсе concourse.

Загружаем и устанавливаем утилиту Fly.
# curl 'https://concourse.interlan.xyz/api/v1/cli?arch=amd64&platform=linux' -o fly
# chmod +x ./fly
# mv ./fly /usr/local/bin/
Авторизуемся.
$ fly -t local login -c https://concourse.interlan.xyz/ -u administrator
Запрашиваем список доступных подключений.
$ fly -t local targets
name url team expiry
local https://concourse.interlan.xyz main Tue, 10 Feb 2026 09:40:17 UTC
Создаем тестовый Pipeline.
jobs:
- name: hello-world-job
plan:
- task: hello-world-task
config:
# Tells Concourse which type of worker this task should run on
platform: linux
# This is one way of telling Concourse which container image to use for a
# task. We'll explain this more when talking about resources
image_resource:
type: registry-image
source:
repository: busybox # images are pulled from docker hub by default
tag: latest
# The command Concourse will run inside the container
# echo "Hello world!"
run:
path: echo
args: [ "Hello world!" ]
Загружаем Pipeline на сервер.
$ fly -t local set-pipeline -p hello-world -c hello.yml
Проверяем, что pipeline отображается в web-интерфейсе.

Запускаем PipeLine.
$ fly -t local set-pipeline -p hello-world -c hello.yml
$ fly -t local unpause-pipeline -p hello-world
$ fly -t local trigger-job --job hello-world/hello-world-job --watch
Запрашиваем список Pipeline.
$ fly -t local pipelines
id name paused public last updated
1 hello-world no no 2026-02-09 16:50:40 +0700 +07
Приостановить Pipeline.
$ fly -t local pause-pipeline -p hello-world
Получить список задач.
$ fly -t local jobs -p hello-world
Удалить Pipeline
$ fly -t local destroy-pipeline -p hello-world




