Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
928c686801 |
4 changed files with 59 additions and 75 deletions
|
|
@ -11,74 +11,48 @@ on:
|
|||
- main
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ secrets.IMAGE_NAME || 'vsdiscoveries/flask-app' }}
|
||||
# Для Docker Hub REGISTRY не нужен - оставляем пустым
|
||||
IMAGE_NAME: ${{ secrets.IMAGE_NAME || 'flask-app' }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || '22' }}
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git config --global http.sslVerify false
|
||||
git clone https://vicsergeev.ru/forgejo/Vic/DummyApp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
ls -la
|
||||
- name: Setup complete
|
||||
run: echo "✅ Setup complete, starting pipeline..."
|
||||
|
||||
test:
|
||||
needs: setup
|
||||
runs-on: docker
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git config --global http.sslVerify false
|
||||
git clone https://vicsergeev.ru/forgejo/Vic/DummyApp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Python
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y python3 python3-pip python3-venv
|
||||
python3 --version
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9' # Исправил на 3.9, т.к. 3.14 еще нет
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
pip3 install -r requirements.txt
|
||||
pip3 install pytest flake8
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install pytest flake8
|
||||
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
|
||||
- name: Test with pytest
|
||||
run: echo "✅ Tests passed!"
|
||||
- name: Test with pytest (опционально)
|
||||
run: |
|
||||
# Добавьте тесты если есть
|
||||
echo "Tests passed!"
|
||||
|
||||
build-and-push:
|
||||
needs: test
|
||||
runs-on: docker
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git config --global http.sslVerify false
|
||||
git clone https://vicsergeev.ru/forgejo/Vic/DummyApp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
|
||||
- name: Install Docker CLI
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y ca-certificates curl
|
||||
curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-26.1.4.tgz -o docker.tgz
|
||||
tar xzf docker.tgz --strip-components=1 -C /usr/bin docker/docker
|
||||
rm docker.tgz
|
||||
docker --version
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
@ -88,6 +62,7 @@ jobs:
|
|||
with:
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
# registry не указываем - по умолчанию Docker Hub
|
||||
|
||||
- name: Get commit hash
|
||||
id: vars
|
||||
|
|
@ -105,32 +80,25 @@ jobs:
|
|||
${{ env.IMAGE_NAME }}:latest
|
||||
${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.IMAGE_TAG }}
|
||||
${{ env.IMAGE_NAME }}:${{ github.run_number }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
COMMIT_HASH=${{ steps.vars.outputs.COMMIT_HASH }}
|
||||
BUILD_TIME=${{ steps.vars.outputs.BUILD_TIME }}
|
||||
|
||||
deploy:
|
||||
needs: build-and-push
|
||||
runs-on: docker
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git config --global http.sslVerify false
|
||||
git clone https://vicsergeev.ru/forgejo/Vic/DummyApp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
apt-get update && apt-get install -y openssh-client
|
||||
mkdir -p /root/.ssh
|
||||
chmod 700 /root/.ssh
|
||||
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" | sed 's/\r$//' > /root/.ssh/deploy_key
|
||||
chmod 600 /root/.ssh/deploy_key
|
||||
|
||||
ssh-keyscan -p ${{ env.DEPLOY_PORT }} -H ${{ env.DEPLOY_HOST }} > /root/.ssh/known_hosts 2>/dev/null || true
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Add host to known_hosts
|
||||
run: |
|
||||
|
|
@ -138,9 +106,10 @@ jobs:
|
|||
|
||||
- name: Deploy to VPS
|
||||
run: |
|
||||
ssh -p ${{ env.DEPLOY_PORT }} -i /root/.ssh/deploy_key -o StrictHostKeyChecking=no -o BatchMode=yes ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'DEPLOY_SCRIPT'
|
||||
ssh -p ${{ env.DEPLOY_PORT }} ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'DEPLOY_SCRIPT'
|
||||
set -e
|
||||
|
||||
# Переменные для деплоя
|
||||
APP_NAME="flask-app"
|
||||
IMAGE_NAME="${{ env.IMAGE_NAME }}"
|
||||
CONTAINER_NAME="flask-app"
|
||||
|
|
@ -149,16 +118,20 @@ jobs:
|
|||
|
||||
echo "🚀 Начинаем деплой на сервер..."
|
||||
|
||||
# Создаем директорию для приложения если её нет
|
||||
mkdir -p $DEPLOY_DIR
|
||||
cd $DEPLOY_DIR
|
||||
|
||||
# Загружаем последний образ (без REGISTRY, т.к. Docker Hub по умолчанию)
|
||||
echo "📦 Загружаем Docker образ с Docker Hub..."
|
||||
docker pull $IMAGE_NAME:latest
|
||||
|
||||
# Останавливаем и удаляем старый контейнер
|
||||
echo "🔄 Перезапускаем контейнер..."
|
||||
docker stop $CONTAINER_NAME 2>/dev/null || true
|
||||
docker rm $CONTAINER_NAME 2>/dev/null || true
|
||||
|
||||
# Запускаем новый контейнер
|
||||
echo "🚀 Запускаем новый контейнер..."
|
||||
docker run -d \
|
||||
--name $CONTAINER_NAME \
|
||||
|
|
@ -170,7 +143,8 @@ jobs:
|
|||
-e SECRET_KEY="${{ secrets.APP_SECRET_KEY }}" \
|
||||
$IMAGE_NAME:latest
|
||||
|
||||
sleep 15
|
||||
# Проверяем здоровье
|
||||
sleep 5
|
||||
if curl -f http://localhost:$PORT/health; then
|
||||
echo "✅ Деплой успешно завершен!"
|
||||
echo "🌐 Приложение доступно на порту $PORT"
|
||||
|
|
@ -180,6 +154,7 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Очищаем старые образы
|
||||
echo "🧹 Очищаем старые Docker образы..."
|
||||
docker image prune -f
|
||||
DEPLOY_SCRIPT
|
||||
|
|
|
|||
23
Dockerfile
23
Dockerfile
|
|
@ -1,21 +1,34 @@
|
|||
FROM python:3.12-slim
|
||||
# Многоступенчатая сборка для оптимизации
|
||||
FROM python:3.14-slim as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Ставим зависимости глобально (доступно всем пользователям)
|
||||
# Устанавливаем зависимости
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Копируем код
|
||||
# Финальный образ
|
||||
FROM python:3.14-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Копируем зависимости из builder
|
||||
COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
|
||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||
|
||||
# Копируем код приложения
|
||||
COPY . .
|
||||
|
||||
# Создаём пользователя и даём права на /app
|
||||
# Создаем пользователя для запуска
|
||||
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
# Экспортируем порт
|
||||
EXPOSE 5000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:5000/health')" || exit 1
|
||||
CMD python -c "import requests; requests.get('http://localhost:5000/health')" || exit 1
|
||||
|
||||
# Запускаем через gunicorn
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "run:app"]
|
||||
11
README.md
11
README.md
|
|
@ -1,9 +1,6 @@
|
|||
# DummyApp for dockerfile training & Forgejo CI/CD
|
||||
My first time
|
||||
# DummyApp
|
||||
|
||||
Dummy app for dockerfile training
|
||||
|
||||
### Dockerfile
|
||||
is created with AI, used as best practices example
|
||||
|
||||
### Success
|
||||
I started with very difficult one - Forgejo has to be setup manualy, runner install seperatly
|
||||
All secerest also done manually. "How to" doc is going to be created in nearest future
|
||||
is created with AI, used as best practices example
|
||||
1
run.py
1
run.py
|
|
@ -3,5 +3,4 @@ from app import create_app
|
|||
app = create_app()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Starting server...")
|
||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
||||
Loading…
Add table
Add a link
Reference in a new issue