239 lines
No EOL
5.7 KiB
Markdown
239 lines
No EOL
5.7 KiB
Markdown
## Рекап успешной конфигурации
|
||
|
||
---
|
||
|
||
### 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@<IP_сервера>
|
||
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.** |