코드를 GitHub에 두면 편하다. 대신 회사의 소스코드가 남의 클라우드에 있고, CI/CD를 쓰려면 또 다른 서비스와 연결해야 하고, 사용자·용량 정책은 언제든 바뀔 수 있다. GitLab은 코드 저장소에 이슈 트래커, 코드리뷰, 위키, 컨테이너 레지스트리, 그리고 CI/CD 실행기까지 전부 묶어 내 서버에 설치할 수 있는 올인원 개발 플랫폼이다. 혼자서도, 팀이 되어도 같은 구성으로 쓸 수 있다.
필요한 것은 RAM 4GB 이상(권장 8GB)의 서버다. 가장 무거운 편에 속하는 셀프호스팅이라는 점만 미리 알아두자.
GitLab은 DevOps 전 과정을 하나로 묶은 오픈소스 플랫폼이다. GitHub과 비교하면 이해가 빠른데, GitHub이 "클라우드 서비스 중심 + 오픈소스 서버판(기능 제한)"이라면 GitLab은 "오픈소스 서버판이 거의 모든 기능을 제공"하는 쪽이다. 무료 CE(Community Edition)로도 개인·소규모 팀이 필요한 것은 대부분 된다.
| 기능 | 내용 |
|---|---|
| 코드 저장소 | 무제한 비공개 저장소, 브랜치 보호, 코드리뷰(MR) |
| CI/CD | .gitlab-ci.yml 하나로 테스트·빌드·배포 파이프라인 |
| 이슈·보드 | 이슈 트래커, 라벨, 칸반 보드, 마일스톤 |
| 위키 | 저장소별 문서 공간 |
| 레지스트리 | 도커 이미지·패키지 저장소 내장 |
| 권한 관리 | 그룹·역할 기반 접근 제어 |
이 중 이 글이 다룰 핵심은 CI/CD다. 코드를 push하면 GitLab이 변경을 감지해, 등록된 Runner(실행기)에게 테스트와 빌드를 시키고 결과를 리포트한다.
flowchart LR
D["개발자 - push"] --> G["GitLab - 저장소·이슈·리뷰"]
T["팀원 - 이슈·코드리뷰"] --> G
G -->|커밋 감지| R["GitLab Runner - 테스트·빌드"]
R -->|결과 보고| G
R -->|성공 시| AR["아티팩트·이미지 배포"]
G --> BK[("백업 - data·설정")]
GitLab 본체(웹UI·저장소·DB)와 Runner는 별도 컨테이너로 운영하는 것이 권장 구성이다. Runner가 빌드 작업을 대신 실행하므로 본체 리소스가 빌드로 오염되지 않는다.
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
hostname: git.example.com
shm_size: 256m
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://git.example.com'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
volumes:
- /opt/docker/gitlab/config:/etc/gitlab
- /opt/docker/gitlab/logs:/var/log/gitlab
- /opt/docker/gitlab/data:/var/opt/gitlab
ports:
- "8081:80"
- "2222:22"
restart: unless-stopped
첫 기동에는 몇 분이 걸린다(초기화가 길다). 초기 root 비밀번호는 24시간 후 자동 삭제되는 파일에 있으니 바로 확인하자:
docker exec -it gitlab cat /etc/gitlab/initial_root_password
root로 로그인해 비밀번호를 변경하고, 일반 사용자 계정을 만들어 root는 예비로 남겨둔다. 서버의 22번 포트를 이미 쓰고 있다면 위처럼 SSH를 2222로 우회하고 clone 주소에 반영한다.
gitlab-runner:
image: gitlab/gitlab-runner:latest
container_name: gitlab-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/docker/gitlab-runner/config:/etc/gitlab-runner
restart: unless-stopped
관리 영역 → CI/CD → 러너에서 등록 토큰을 발급받고:
docker exec -it gitlab-runner gitlab-runner register \
--url https://git.example.com --token 발급토큰 --executor docker \
--docker-image alpine:latest
저장소 루트에 .gitlab-ci.yml 하나면 끝난다.
stages:
- test
test-job:
stage: test
image: alpine:latest
script:
- echo "테스트 실행"
push하는 순간 파이프라인이 도는 것을 저장소의 CI/CD 메뉴에서 볼 수 있다. 여기에 언어별 테스트, 도커 이미지 빌드, 배포 스크립트를 붙여가면 된다.
백업은 두 조각이다. docker exec gitlab gitlab-backup create가 저장소·DB·업로드를 묶어 덤프한다. 함정은 설정 디렉터리(/etc/gitlab)는 백업에 포함되지 않는다는 것 — 이 안의 secrets 파일 없이는 백업본의 암호화 데이터를 복구할 수 없다. 백업 + 설정, 둘 다 챙긴다.
메이저 업그레이드는 계단식으로. GitLab은 최신으로 한 번에 뛰는 것을 허용하지 않는다. 공식 문서의 업그레이드 경로(예: 16.x → 17.x 중간 버전들)를 순서대로 밟아야 한다. 급하게 뛰면 DB 마이그레이션이 멈춘다.
메모리 여유를 두자. RAM 4GB 미만에서는 sidekiq(백그라운드 작업)가 OOM으로 죽는 일이 생긴다. swap을 크게 잡아두면 최소 사양에서도 버틴다.
| 증상 | 원인 | 해결 |
|---|---|---|
| 접속하면 502 | 기동 중이거나 메모리 부족 | 기동 대기(수 분), 메모리·swap 확인 |
| clone이 안 된다 | SSH 포트·external_url 불일치 | gitlab_shell_ssh_port와 주소 확인 |
| 파이프라인이 대기만 한다 | Runner 미등록·오프라인 | 러너 상태 확인, 재등록 |
| 업데이트 후 오류 | 업그레이드 경로 건너뜀 | 공식 경로에 따라 단계적 진행 |
| 이메일 발송 실패 | SMTP 미설정 | gitlab.rb에 SMTP 설정 추가 |
혼자 공개 프로젝트면 GitHub이 편하다. 사내 코드 보관, 데이터 주권, CI/CD 무제한(자원 내), 계정 정책 통제가 필요해지면 GitLab 셀프호스팅이 답이다. 둘의 사용 경험은 상당히 비슷해서 이동 비용도 크지 않다.
RAM 4GB가 현실적인 최소선(반드시 swap 설정), 권장은 8GB다. 저장소와 CI 빌드 아티팩트가 쌓이는 만큼 디스크도 여유를 둔다.
push 시 테스트 실행, 도커 이미지 빌드 후 내장 레지스트리 push, 서버로 SSH 접속해 배포 — 이 일련의 흐름이 .gitlab-ci.yml 하나로 자동화된다. 이 시리즈의 다른 서비스들을 업데이트하는 배포 자동화에도 쓸 수 있다.
서버 한 대로 충분하다 연재 목차 — 시리즈 소개 · 1화. Home Assistant · 2화. Frigate + go2rtc · 3화. Seafile 13 · 4화. Immich · 5화. Vaultwarden · 6화. Mailcow · 7화. MinIO · 8화. Umami
실제 운영 서버에서 러너 분리 구성으로 사용 중입니다.
| 이전 | 8화. Umami — 구글 애널리틱스 없이 방문자 통계 보기 | 2026-10-01 | |
|---|---|---|---|
| 다음 | 10화. Portainer — 도커를 터미널 없이 다루기 (웹 관리 콘솔) | 2026-10-01 |