목차
팀 프로젝트에서 CI/CD 환경을 구축하기 위해 Jenkins를 도입했다.
하지만 AWS Free-Tier 환경에서는 비용 절감을 위해 빈번한 terraform apply/destroy 작업이 발생했고, 매번 수동으로 Jenkins를 재설치하는 과정은 비효율적이라고 판단했다.
이를 해결하기 위해 Packer와 Terraform을 조합해 Jenkins EC2 자동화 파이프라인을 설계했다.
이번 글에서는 Jenkins EC2를 자동화하는 세 가지 방법을 비교하고, 가장 범용적이고 실무적인 접근인 “Packer로 Docker 기반 AMI를 생성하고 Terraform으로 Jenkins 컨테이너를 실행하는 방식”을 구현한다.
Jenkins EC2 자동화의 세 가지 방법
Packer로 Jenkins까지 설치된 AMI 생성
•
설명: Jenkins를 EC2 이미지에 직접 설치해 AMI로 만들어 둔다.
•
장점: 배포 즉시 Jenkins 실행 가능구성 단순
•
단점: Jenkins 버전 변경 시 AMI 재빌드 필요환경 유연성 낮음
•
권장 대상: 개인 프로젝트, 단일 서버
Packer로 Docker + Jenkins를 함께 설치한 AMI 생성
•
설명: Docker를 설치하고 Jenkins 컨테이너까지 포함한 AMI를 만든다.
•
장점: 컨테이너 기반 Jenkins빠른 기동
•
단점: Jenkins 컨테이너 버전 고정AMI 교체 주기 여전히 필요
•
권장 대상: 소규모 DevOps 환경
Packer로 Docker만 설치된 AMI 생성 + Terraform에서 Jenkins 컨테이너 실행
•
설명: Packer는 Docker 환경만 구성하고, Terraform이 런타임에 Jenkins 컨테이너를 실행한다.
•
장점: AMI 범용성 높음Jenkins 교체 간편IaC 관리 용이
•
단점: 초기 구성 복잡
•
권장 대상: 일반적인 현대 DevOps 환경
Docker 기반 AMI 생성 + Terraform으로 Jenkins 컨테이너 실행
이번 글에서는 ③번 구조를 실습한다. 즉, Packer는 Docker 환경만 구축하고, Terraform이 Jenkins를 컨테이너로 실행한다. 이 방식은 Jenkins뿐 아니라 다른 서비스에도 동일하게 적용할 수 있다.
전체 구조 개요
Packer → (Docker 설치된 AMI 빌드)
Terraform → (해당 AMI 기반 EC2 생성 + Jenkins 컨테이너 실행)
Plain Text
복사
•
Packer: 표준 Docker 베이스 AMI 생성
•
Terraform: 인스턴스 생성 후 user_data로 Jenkins 컨테이너 자동 실행
•
결과: EC2 부팅 시 Jenkins가 컨테이너 형태로 즉시 실행됨
Packer로 Docker 기반 AMI 빌드
docker-base.pkr.hcl 파일을 생성한다.
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = ">= 1.2.0"
}
}
}
source "amazon-ebs" "docker_base" {
region = "ap-northeast-2"
ami_name = "docker-base-{{timestamp}}"
instance_type = "t3.micro"
ssh_username = "ubuntu"
source_ami_filter {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
owners = ["099720109477"]
most_recent = true
}
tags = {
Name = "docker-base-ami"
}
}
build {
sources = ["source.amazon-ebs.docker_base"]
provisioner "shell" {
inline = [
"sudo apt update -y",
"sudo apt install -y ca-certificates curl gnupg lsb-release",
"sudo mkdir -m 0755 -p /etc/apt/keyrings",
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg",
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt update -y",
"sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin",
"sudo usermod -aG docker ubuntu",
"sudo systemctl enable docker"
]
}
}
HCL
복사
구성 요소 | 설명 |
source.amazon-ebs | AWS EC2용 AMI 빌더 |
provisioner.shell | Docker를 설치하고 부팅 시 자동 실행되도록 설정 |
ami_name | docker-base-<timestamp> 형태로 AMI 이름 지정 |
Packer 빌드 실행
packer init .
packer validate docker-base.pkr.hcl
packer build docker-base.pkr.hcl
Bash
복사
완료되면 AWS 콘솔의 EC2 → AMI 메뉴에서 docker-base-<timestamp> 이름의 이미지가 생성된다.
이제 이 AMI가 모든 배포의 공통 베이스가 된다.
Terraform으로 Jenkins 컨테이너 실행
main.tf 파일을 작성한다.
data "aws_ami" "docker_base" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["docker-base-*"]
}
}
resource "aws_instance" "jenkins" {
ami = data.aws_ami.docker_base.id
instance_type = "t3.micro"
subnet_id = aws_subnet.public_a.id
vpc_security_group_ids = [aws_security_group.jenkins.id]
key_name = var.key_name
user_data = <<-EOF
#!/bin/bash
docker pull jenkins/jenkins:lts-jdk17
docker run -d \
-p 8080:8080 -p 50000:50000 \
-v /var/jenkins_home:/var/jenkins_home \
--name jenkins \
jenkins/jenkins:lts-jdk17
EOF
tags = {
Name = "jenkins-docker-ec2"
}
}
HCL
복사
•
Terraform이 docker-base AMI로 EC2 인스턴스를 생성한다.
•
부팅 후 user_data 스크립트가 Jenkins 컨테이너를 자동 실행한다.
•
Jenkins는 8080 포트에서 접근 가능하며, /var/jenkins_home에 데이터가 저장된다.
배포 실행
terraform init
terraform apply
Bash
복사
배포 후 EC2에 SSH 접속하여 Jenkins 컨테이너가 정상 기동 중인지 확인한다.
ssh -i <keypair> ubuntu@<ec2_ip>
sudo docker ps
Bash
복사
결과 예시:
CONTAINER ID IMAGE COMMAND STATUS PORTS
a13c3c... jenkins/jenkins:lts-jdk17 "/usr/bin/tini -- /u…" Up 2 minutes 0.0.0.0:8080->8080/tcp
Bash
복사
Jenkins 업데이트 전략
Docker 기반 Jenkins의 장점은 버전 교체가 AMI 재빌드 없이 가능하다는 점이다.
EC2 내 혹은 Terraform 변수로 Jenkins 이미지를 관리할 수 있다.
# Bash
sudo docker pull jenkins/jenkins:lts-jdk17
sudo systemctl restart docker
Bash
복사
# Terraform
variable "jenkins_image" {
default = "jenkins/jenkins:lts-jdk17"
}
HCL
복사
마무리
이번 구축을 통해 Packer와 Terraform을 활용한 Jenkins EC2 완전 자동화 구조를 만들었다.
덕분에 terraform apply/destroy를 반복해도 Jenkins 환경이 일관되게 유지되며, Docker 기반으로 Jenkins를 컨테이너화했기 때문에 업데이트나 재배포 시에도 빠르고 유연한 관리가 가능하다.
다만 Jenkins의 데이터를 지속적으로 유지하려면 EBS 볼륨 스냅샷 또는 외부 스토리지 마운트 등의 추가 구성이 필요하다.
또한 Terraform의 user_data는 첫 부팅 시 1회만 실행되기 때문에, 초기 컨테이너 실행이 실패할 경우에는 Ansible 등을 함께 사용하는 것이 일반적이다.

