diff --git a/Recap.md b/Recap.md new file mode 100644 index 0000000..888101b --- /dev/null +++ b/Recap.md @@ -0,0 +1,239 @@ +## Рекап успешной конфигурации + +--- + +### 1. GitLab в Docker + +**Запуск контейнера** (уже был настроен, ключевое — порты): +```bash +docker run -d \ + --hostname gitlab.local \ + --publish 85:80 \ + --publish 443:443 \ + --publish 2223:22 \ + --name gitlab \ + --restart always \ + -v /srv/gitlab/config:/etc/gitlab \ + -v /srv/gitlab/logs:/var/log/gitlab \ + -v /srv/gitlab/data:/var/opt/gitlab \ + gitlab/gitlab-ce:latest +``` + +**Критическая настройка внутри контейнера** (чтобы nginx слушал на всех интерфейсах): +```bash +docker exec -it gitlab bash + +cat > /etc/gitlab/gitlab.rb << 'EOF' +external_url 'http://10.0.2.15:85' +nginx['listen_addresses'] = ['0.0.0.0'] +nginx['listen_port'] = 80 +EOF + +gitlab-ctl reconfigure +exit +docker restart gitlab +``` + +--- + +### 2. GitLab Runner + +**Установка:** +```bash +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 +sudo chmod +x /usr/local/bin/gitlab-runner +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start +``` + +**Регистрация** (`http://172.17.0.1:85` — IP docker bridge, доступный изнутри контейнеров): +```bash +sudo gitlab-runner register +# URL: http://172.17.0.1:85 +# Token: [из GitLab → Settings → CI/CD → Runners] +# Executor: docker +# Default image: docker:latest +``` + +**Конфиг `/etc/gitlab-runner/config.toml`** (главное — `url` и `clone_url` на IP docker bridge): +```toml +[[runners]] + name = "gitlab-runner" + url = "http://172.17.0.1:85" + token = "..." + executor = "docker" + clone_url = "http://172.17.0.1:85" + + [runners.docker] + image = "docker:latest" + privileged = true +``` + +**Разрешить untagged jobs** в GitLab → Settings → CI/CD → Runners → Edit → ☑️ Run untagged jobs. + +--- + +### 3. Структура проекта + +``` +myapp/ +├── main.go +├── go.mod +├── Dockerfile +└── .gitlab-ci.yml +``` + +**`main.go`** — минимальный HTTP-сервер: +```go +package main + +import ( + "fmt" + "net/http" + "os" + "time" +) + +func main() { + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello from CI/CD!\nVersion: 1.0.0\nTime: %s\n", time.Now().Format(time.RFC3339)) + }) + + http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + fmt.Fprintln(w, `{"status":"ok"}`) + }) + + fmt.Printf("Server starting on :%s\n", port) + http.ListenAndServe(":"+port, nil) +} +``` + +**`go.mod`**: +```text +module myapp + +go 1.23 +``` + +**`Dockerfile`** — копирует уже собранный бинарник (не собирает заново): +```dockerfile +FROM alpine:latest +COPY server /server +RUN chmod +x /server +ENV PORT=8080 +EXPOSE 8080 +ENTRYPOINT ["/server"] +``` + +--- + +### 4. CI/CD Pipeline (`.gitlab-ci.yml`) + +```yaml +stages: + - build + - deploy + +build: + stage: build + image: golang:1.23-alpine + script: + - CGO_ENABLED=0 go build -ldflags="-s -w" -o server main.go + artifacts: + paths: + - server + +deploy: + stage: deploy + image: alpine:latest + dependencies: + - build + before_script: + - apk add --no-cache openssh-client + - mkdir -p ~/.ssh && chmod 700 ~/.ssh + - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa + - ssh-keyscan -H $DEPLOY_HOST >> ~/.ssh/known_hosts + script: + - | + ssh $DEPLOY_USER@$DEPLOY_HOST "mkdir -p ~/myapp" + scp server Dockerfile $DEPLOY_USER@$DEPLOY_HOST:~/myapp/ + ssh $DEPLOY_USER@$DEPLOY_HOST << EOF + set -e + cd ~/myapp + docker stop myapp || true + docker rm myapp || true + docker build -t myapp:latest . + docker run -d --name myapp --restart unless-stopped -p 8080:8080 myapp:latest + docker image prune -f + docker ps | grep myapp + EOF + only: + - master +``` + +--- + +### 5. Целевой сервер (деплой) + +**SSH-ключи** (генерируем на сервере с GitLab): +```bash +ssh-keygen -t ed25519 -C "gitlab-deploy" -f ~/.ssh/gitlab_deploy +``` + +**На целевом сервере:** +```bash +sudo useradd -m -s /bin/bash deploy +sudo usermod -aG docker deploy + +sudo mkdir -p /home/deploy/.ssh +sudo nano /home/deploy/.ssh/authorized_keys +# Вставить содержимое ~/.ssh/gitlab_deploy.pub + +sudo chmod 700 /home/deploy/.ssh +sudo chmod 600 /home/deploy/.ssh/authorized_keys +sudo chown -R deploy:deploy /home/deploy/.ssh +sudo reboot +``` + +--- + +### 6. GitLab Variables + +**Project → Settings → CI/CD → Variables:** + +| Variable | Значение | +|----------|----------| +| `SSH_PRIVATE_KEY` | Содержимое `~/.ssh/gitlab_deploy` (приватный ключ) | +| `DEPLOY_HOST` | IP целевого сервера | +| `DEPLOY_USER` | `deploy` | + +--- + +### 7. Проверка деплоя + +```bash +ssh deploy@ +docker ps +curl http://localhost:8080 +curl http://localhost:8080/health +``` + +--- + +### Итоговые цифры + +| Параметр | Значение | +|----------|----------| +| Размер Docker-образа приложения | ~10 МБ | +| Внешних зависимостей | 0 | +| Этапов CI/CD | 2 (build → deploy) | +| Размер runner-образа | не критичен (используется стандартный alpine) | + +**Push в `master` → build → scp на сервер → docker build → docker run → приложение доступно на порту 8080.** \ No newline at end of file