Configuring CI/CD for Your Website with TeamCity
TeamCity is a CI/CD server from JetBrains. It supports complex pipelines, parallel steps, its own Kotlin DSL, and tight integration with IntelliJ IDEA. Popular in corporate environments and .NET projects.
Installing TeamCity
# Docker Compose
services:
teamcity-server:
image: jetbrains/teamcity-server:2024.03
ports:
- "8111:8111"
volumes:
- ./teamcity-data:/data/teamcity_server/datadir
- ./teamcity-logs:/opt/teamcity/logs
teamcity-agent:
image: jetbrains/teamcity-agent:2024.03
environment:
SERVER_URL: "http://teamcity-server:8111"
AGENT_NAME: "linux-agent-1"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Kotlin DSL — Configuration as Code
// .teamcity/settings.kts
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.buildSteps.*
import jetbrains.buildServer.configs.kotlin.triggers.*
version = "2024.03"
project {
buildType(Build)
buildType(Test)
buildType(Deploy)
buildTypesOrder = arrayListOf(Build, Test, Deploy)
}
object Build : BuildType({
name = "Build"
vcs { root(DslContext.settingsRoot) }
steps {
nodeJS {
shellScript = "npm ci && npm run build"
}
}
artifactRules = "dist/** => dist.zip"
})
object Test : BuildType({
name = "Test"
dependencies {
snapshot(Build) {}
}
steps {
script {
scriptContent = """
npm ci
npm test -- --coverage --ci
""".trimIndent()
}
}
failureConditions {
testFailure = true
errorMessage = true
}
})
object Deploy : BuildType({
name = "Deploy to Production"
type = Type.DEPLOYMENT
dependencies {
snapshot(Test) {}
artifacts(Build) {
artifactRules = "dist.zip => ."
}
}
params {
param("deploy.env", "production")
}
steps {
script {
scriptContent = """
unzip dist.zip -d /var/www/app/
sudo systemctl reload nginx
""".trimIndent()
}
}
triggers {
vcs {
branchFilter = "+:refs/heads/main"
}
}
})
Deploy via SSH
// SSH Upload Step
sshExec {
commands = """
cd /var/www/app
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo systemctl reload php8.3-fpm
""".trimIndent()
targetUrl = "deploy-server.example.com"
authMethod = uploadedKey {
username = "deploy"
key = "deploy_key"
}
}
Docker Build in TeamCity
steps {
dockerCommand {
commandType = build {
source = file { path = "Dockerfile" }
namesAndTags = "registry.example.com/myapp:%build.counter%"
commandArgs = "--no-cache"
}
}
dockerCommand {
commandType = push {
namesAndTags = "registry.example.com/myapp:%build.counter%"
}
}
}
Parameters and Templates
// Template for multiple environments
template("DeployTemplate") {
params {
param("env.name", "")
param("env.url", "")
param("ssh.host", "")
}
steps {
script {
scriptContent = "deploy.sh %env.name% %env.url%"
}
}
}
object DeployStaging : BuildType({
templates(DeployTemplate)
params {
param("env.name", "staging")
param("env.url", "https://staging.example.com")
param("ssh.host", "staging.server.com")
}
})
Notifications
TeamCity supports notifications to Slack, email, Telegram:
// Email on build
emailNotifier {
sendTo = "[email protected]"
events {
buildFailed()
firstSuccessAfterFailure()
}
}
Implementation Timeline
Basic pipeline Build → Test → Deploy: 2–3 days. Full setup with multiple environments, templates, and notifications: 5–7 days.







