Compare commits
No commits in common. "16f3e17a3d6b0e999ae7b35c774ed006a0c7abc9" and "cc2615d7072510eff153b1b8d7e1be7d7d627dd7" have entirely different histories.
16f3e17a3d
...
cc2615d707
10
.env
10
.env
@ -1,10 +0,0 @@
|
|||||||
#Пример .env файла. Используем его чтобы не указывать чувствительные данные (пароли, ключи, API и т.д.) напрямую в коде
|
|
||||||
# PostgreSQL
|
|
||||||
POSTGRES_USER=user
|
|
||||||
POSTGRES_PASSWORD=password
|
|
||||||
POSTGRES_DB=website
|
|
||||||
DB_HOST=database
|
|
||||||
|
|
||||||
# Nginx bublick & private key
|
|
||||||
SSL_CERT_FILE=./nginx/ssl/domain.crt
|
|
||||||
SSL_KEY_FILE=./nginx/ssl/domain.key
|
|
@ -1,29 +0,0 @@
|
|||||||
name: Deploy to Server
|
|
||||||
|
|
||||||
on:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup SSH Key
|
|
||||||
uses: webfactory/ssh-agent@v0.7.0
|
|
||||||
with:
|
|
||||||
ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
||||||
|
|
||||||
- name: Add Known Host
|
|
||||||
run: ssh-keyscan ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Deploy to Server
|
|
||||||
run: |
|
|
||||||
ssh -o StrictHostKeyChecking=no ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} "
|
|
||||||
cd ${{ secrets.PROJECT_PATH }} &&
|
|
||||||
git pull origin master &&
|
|
||||||
docker-compose down --remove-orphans &&
|
|
||||||
docker-compose up -d --build
|
|
||||||
"
|
|
73
README.md
73
README.md
@ -1,72 +1 @@
|
|||||||
# 🚀 Web Application with Docker, PostgreSQL & Flask
|
Первый пуш, не гарантирую работоспособность этого кода
|
||||||
|
|
||||||
Простое веб-приложение с авторизацией, которое можно использовать как основу для собственного проекта.
|
|
||||||
|
|
||||||
## 🌟 Особенности проекта
|
|
||||||
|
|
||||||
- **Docker-ориентированный** (сборка через compose)
|
|
||||||
- **Безопасность**: секреты через ".env", healthcheck для БД
|
|
||||||
- **Автоматический деплой** через Git hooks
|
|
||||||
- **Логирование** операций деплоя
|
|
||||||
|
|
||||||
## 🛠 Технологический стек
|
|
||||||
|
|
||||||
- Frontend: Nginx со статическим html
|
|
||||||
- Backend: Python Flask
|
|
||||||
- DataBase: PostgreSQL
|
|
||||||
- Infrastructure: Docker, Docker Compose
|
|
||||||
- CI/CD: Git hooks
|
|
||||||
|
|
||||||
🔧 Архитектура проекта
|
|
||||||
Copy
|
|
||||||
container-web-app/
|
|
||||||
│
|
|
||||||
├── backend/
|
|
||||||
│ ├── requirements.txt
|
|
||||||
│ └── server.py
|
|
||||||
│
|
|
||||||
├── db/
|
|
||||||
│ └── init.sql
|
|
||||||
│
|
|
||||||
├── frontend/
|
|
||||||
│ ├── static/
|
|
||||||
│ └── index.html
|
|
||||||
│
|
|
||||||
├── nginx/
|
|
||||||
│ ├── ssl/
|
|
||||||
│ │ ├── domain.crt
|
|
||||||
│ │ ├── domain.conf
|
|
||||||
│ │ └── domain.key
|
|
||||||
│ └── nginx.conf
|
|
||||||
│
|
|
||||||
├── scripts/
|
|
||||||
│ └── post-receive
|
|
||||||
│
|
|
||||||
├── .env
|
|
||||||
├── docker-compose.yaml
|
|
||||||
└── README.md
|
|
||||||
🔒 Безопасность
|
|
||||||
Все секреты хранятся в .env (в git не коммитятся)
|
|
||||||
|
|
||||||
Healthcheck для мониторинга состояния PostgreSQL
|
|
||||||
|
|
||||||
## CI/CD:
|
|
||||||
|
|
||||||
Автоматический деплой через Git hooks
|
|
||||||
|
|
||||||
Скрипт деплоя с логированием (/var/log/deploy.log)
|
|
||||||
|
|
||||||
## Infrastructure as Code:
|
|
||||||
|
|
||||||
Полная воспроизводимость через Docker
|
|
||||||
|
|
||||||
Версионирование образов
|
|
||||||
|
|
||||||
## 📈 Дальнейшее развитие
|
|
||||||
- Добавить тесты (pytest)
|
|
||||||
|
|
||||||
- Настроить GitHub Actions для CI
|
|
||||||
|
|
||||||
- Реализовать балансировку нагрузки
|
|
||||||
|
|
||||||
- Добавить мониторинг (Prometheus + Grafana)
|
|
@ -1,3 +1,2 @@
|
|||||||
Flask
|
Flask
|
||||||
psycopg2-binary
|
psycopg2-binary
|
||||||
python-dotenv
|
|
@ -1,26 +1,20 @@
|
|||||||
from flask import Flask, request, render_template
|
from flask import Flask, request, render_template
|
||||||
import psycopg2
|
import psycopg2
|
||||||
import os
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
|
|
||||||
load_dotenv()
|
|
||||||
|
|
||||||
app = Flask(__name__, template_folder='/media/frontend')
|
app = Flask(__name__, template_folder='/media/frontend')
|
||||||
|
|
||||||
|
|
||||||
DATABASE = {
|
DATABASE = {
|
||||||
'dbname': os.getenv('POSTGRES_DB'),
|
'dbname': 'WebSite',
|
||||||
'user': os.getenv('POSTGRES_USER'),
|
'user': 'User',
|
||||||
'password': os.getenv('POSTGRES_PASSWORD'),
|
'password': 'Password',
|
||||||
'host': os.getenv('DB_HOST')
|
'host': 'DataBase',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_db_connection():
|
def get_db_connection():
|
||||||
try:
|
conn = psycopg2.connect(**DATABASE)
|
||||||
conn = psycopg2.connect(**DATABASE)
|
return conn
|
||||||
return conn
|
|
||||||
except psycopg2.Error as e:
|
|
||||||
print(f"Ошибка подключения к базе данных: {e}")
|
|
||||||
raise
|
|
||||||
|
|
||||||
@app.route('/', methods=['GET'])
|
@app.route('/', methods=['GET'])
|
||||||
def index():
|
def index():
|
||||||
@ -29,50 +23,45 @@ def index():
|
|||||||
@app.route('/submit', methods=['POST'])
|
@app.route('/submit', methods=['POST'])
|
||||||
def submit():
|
def submit():
|
||||||
action = request.form.get('action')
|
action = request.form.get('action')
|
||||||
message = ""
|
|
||||||
|
|
||||||
try:
|
if action == 'Login':
|
||||||
|
username = request.form.get('username')
|
||||||
|
password = request.form.get('password')
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
|
||||||
if action == 'Login':
|
cur.execute('SELECT * FROM users WHERE username = %s AND password = %s', (username, password))
|
||||||
username = request.form.get('username')
|
user = cur.fetchone()
|
||||||
password = request.form.get('password')
|
|
||||||
|
|
||||||
cur.execute(
|
cur.close()
|
||||||
'SELECT * FROM users WHERE username = %s AND password = %s',
|
conn.close()
|
||||||
(username, password)
|
|
||||||
)
|
|
||||||
user = cur.fetchone()
|
|
||||||
|
|
||||||
message = "Успешный вход!" if user else "Неправильные имя пользователя или пароль!"
|
|
||||||
|
|
||||||
elif action == 'Register':
|
|
||||||
new_username = request.form.get('new_username')
|
|
||||||
new_password = request.form.get('new_password')
|
|
||||||
|
|
||||||
cur.execute('SELECT * FROM users WHERE username = %s', (new_username,))
|
|
||||||
if cur.fetchone():
|
|
||||||
message = "Пользователь уже существует!"
|
|
||||||
else:
|
|
||||||
cur.execute(
|
|
||||||
'INSERT INTO users (username, password) VALUES (%s, %s)',
|
|
||||||
(new_username, new_password)
|
|
||||||
)
|
|
||||||
conn.commit()
|
|
||||||
message = "Успешная регистрация!"
|
|
||||||
|
|
||||||
|
if user:
|
||||||
|
message = "Login successful!"
|
||||||
else:
|
else:
|
||||||
message = "Неизвестное действие"
|
message = "Invalid username or password."
|
||||||
|
|
||||||
except psycopg2.Error as e:
|
elif action == 'Register':
|
||||||
conn.rollback()
|
new_username = request.form.get('new_username')
|
||||||
message = f"Ошибка базы данных: {e}"
|
new_password = request.form.get('new_password')
|
||||||
finally:
|
|
||||||
if 'cur' in locals():
|
conn = get_db_connection()
|
||||||
cur.close()
|
cur = conn.cursor()
|
||||||
if 'conn' in locals():
|
|
||||||
conn.close()
|
cur.execute('SELECT * FROM users WHERE username = %s', (new_username,))
|
||||||
|
if cur.fetchone():
|
||||||
|
message = "User already exists!"
|
||||||
|
else:
|
||||||
|
cur.execute('INSERT INTO users (username, password) VALUES (%s, %s)', (new_username, new_password))
|
||||||
|
conn.commit()
|
||||||
|
message = "Registration successful!"
|
||||||
|
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
else:
|
||||||
|
message = "Invalid action."
|
||||||
|
|
||||||
return render_template('index.html', message=message)
|
return render_template('index.html', message=message)
|
||||||
|
|
||||||
|
@ -1,40 +1,44 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name your_doman.com www.your_doman.com;
|
server_name your_domain.com;
|
||||||
return 301 https://your_doman.com$request_uri;
|
return 301 https://your_domain.com$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
server_name your_doman.com www.your_doman.com;
|
server_name your_domain.com;
|
||||||
|
|
||||||
|
|
||||||
ssl_certificate /etc/nginx/sites-available/domain.crt;
|
ssl_certificate /etc/nginx/sites-available/domain.crt;
|
||||||
ssl_certificate_key /etc/nginx/sites-available/domain.key;
|
ssl_certificate_key /etc/nginx/sites-available/domain.key;
|
||||||
|
|
||||||
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
location /submit {
|
location /submit {
|
||||||
proxy_pass http://backend_part:5000;
|
proxy_pass http://backend_part:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
}
|
||||||
}
|
location /api {
|
||||||
|
proxy_pass http://backend_part:5000/;
|
||||||
}
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
conf/domain.crt
Normal file
1
conf/domain.crt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Наш сертификат
|
1
conf/domain.key
Normal file
1
conf/domain.key
Normal file
@ -0,0 +1 @@
|
|||||||
|
Приватный ключ
|
@ -1,51 +0,0 @@
|
|||||||
services:
|
|
||||||
database:
|
|
||||||
image: postgres:17.4-alpine3.21
|
|
||||||
container_name: database
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
|
||||||
POSTGRES_USER: ${POSTGRES_USER}
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
|
|
||||||
#Монтируем директорию на хосте, чтобы при повторных "docker-compose up" таблицы с нашими данными сохранялись
|
|
||||||
volumes:
|
|
||||||
- /database:/var/lib/postgresql/data
|
|
||||||
cpus: '0.15'
|
|
||||||
mem_limit: 256M
|
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U admin -WebSite"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
webserver:
|
|
||||||
image: nginx:1.27.4-alpine
|
|
||||||
container_name: webserver
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- /WebApp/frontend:/usr/share/nginx/html
|
|
||||||
- /WebApp/nginx/ssl:/etc/nginx/sites-available
|
|
||||||
- /WebApp/nginx/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- database
|
|
||||||
- backend
|
|
||||||
cpus: '0.15'
|
|
||||||
mem_limit: 256M
|
|
||||||
backend:
|
|
||||||
image: python:3.9
|
|
||||||
container_name: backend_part
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
volumes:
|
|
||||||
- /WebApp/backend:/media/backend
|
|
||||||
working_dir: /media/backend
|
|
||||||
command: >
|
|
||||||
sh -c "pip install -r requirements.txt && python server.py"
|
|
||||||
cpus: '0.35'
|
|
||||||
mem_limit: 256M
|
|
51
docker/docker-compose.yml
Normal file
51
docker/docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
DataBase:
|
||||||
|
image: postgres:latest
|
||||||
|
container_name: DataBase
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
#Так никто не делает в реальных кейсах, я просто даун, не умею работать с секретами (опция secrets)
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: user
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
POSTGRES_DB: WebSite
|
||||||
|
volumes:
|
||||||
|
- /home/git/myprojects/database:/var/lib/postgresql/data
|
||||||
|
cpus: '0.15'
|
||||||
|
mem_limit: 256M
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U admin -WebSite"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
webserver:
|
||||||
|
image: nginx:latest
|
||||||
|
container_name: WebServer
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- /home/git/myprojects/WorkServer/frontend:/usr/share/nginx/html
|
||||||
|
- /home/git/myprojects/WorkServer/conf:/etc/nginx/sites-available
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- DataBase
|
||||||
|
- backend
|
||||||
|
cpus: '0.15'
|
||||||
|
mem_limit: 256M
|
||||||
|
backend:
|
||||||
|
image: python:3.9
|
||||||
|
container_name: backend_part
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
volumes:
|
||||||
|
- /home/git/myprojects/WorkServer/backend:/media/backend
|
||||||
|
- /home/git/myprojects/WorkServer/frontend:/media/frontend
|
||||||
|
working_dir: /media/backend
|
||||||
|
command: >
|
||||||
|
sh -c "pip install -r requirements.txt && python server.py"
|
||||||
|
cpus: '0.35'
|
||||||
|
mem_limit: 256M
|
3
docker/dockfile/Dockerfile
Normal file
3
docker/dockfile/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM nginx:v1
|
||||||
|
|
||||||
|
COPY nginx.conf /etc/nginx/nginx.conf
|
@ -1,32 +1,32 @@
|
|||||||
|
|
||||||
user nginx;
|
user nginx;
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log notice;
|
error_log /var/log/nginx/error.log notice;
|
||||||
pid /var/run/nginx.pid;
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
http {
|
http {
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
sendfile on;
|
sendfile on;
|
||||||
#tcp_nopush on;
|
#tcp_nopush on;
|
||||||
|
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
|
|
||||||
#gzip on;
|
#gzip on;
|
||||||
|
|
||||||
include /etc/nginx/sites-available/domain.conf;
|
include /etc/nginx/sites-available/domain.conf;
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
username VARCHAR(50) UNIQUE NOT NULL,
|
username VARCHAR(50) UNIQUE NOT NULL,
|
||||||
password VARCHAR(50) NOT NULL
|
password VARCHAR(50) NOT NULL
|
||||||
);
|
);
|
@ -1,36 +1,36 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Login and Register Form</title>
|
<title>Login and Register Form</title>
|
||||||
<link rel="stylesheet" href="./static/css/styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<h1>Login Form</h1>
|
<h1>Login Form</h1>
|
||||||
<form action="/submit" method="post">
|
<form action="/submit" method="post">
|
||||||
<label for="username">Username:</label><br>
|
<label for="username">Username:</label><br>
|
||||||
<input type="text" id="username" name="username" required><br><br>
|
<input type="text" id="username" name="username" required><br><br>
|
||||||
|
|
||||||
<label for="password">Password:</label><br>
|
<label for="password">Password:</label><br>
|
||||||
<input type="password" id="password" name="password" required><br><br>
|
<input type="password" id="password" name="password" required><br><br>
|
||||||
|
|
||||||
<button type="submit" name="action" value="Login">Login</button>
|
<button type="submit" name="action" value="Login">Login</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<h1>Register Form</h1>
|
<h1>Register Form</h1>
|
||||||
<form action="/submit" method="post">
|
<form action="/submit" method="post">
|
||||||
<label for="new_username">Username:</label><br>
|
<label for="new_username">Username:</label><br>
|
||||||
<input type="text" id="new_username" name="new_username" required><br><br>
|
<input type="text" id="new_username" name="new_username" required><br><br>
|
||||||
|
|
||||||
<label for="new_password">Password:</label><br>
|
<label for="new_password">Password:</label><br>
|
||||||
<input type="password" id="new_password" name="new_password" required><br><br>
|
<input type="password" id="new_password" name="new_password" required><br><br>
|
||||||
|
|
||||||
<button type="submit" name="action" value="Register">Register</button>
|
<button type="submit" name="action" value="Register">Register</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1 +0,0 @@
|
|||||||
Наш публичный ключ
|
|
@ -1 +0,0 @@
|
|||||||
Наш приватный ключ
|
|
21
post-receive
Normal file
21
post-receive
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
TARGET="/home/git/myprojects/WorkServer"
|
||||||
|
GIT_DIR="/home/git/myprojects/web"
|
||||||
|
BRANCH="master"
|
||||||
|
|
||||||
|
git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
||||||
|
|
||||||
|
cd /home/git/myprojects/WorkServer/docker
|
||||||
|
|
||||||
|
#docker-compose block:
|
||||||
|
|
||||||
|
# 1
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
# 2
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 3
|
||||||
|
docker-compose up -d
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
TARGET="path to work repo"
|
|
||||||
GIT_DIR="Path to .git repo"
|
|
||||||
BRANCH="master"
|
|
||||||
LOG_FILE="/var/log/deploy.log"
|
|
||||||
|
|
||||||
exec > >(tee -a "$LOG_FILE") 2>&1
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting deploy..."
|
|
||||||
git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
|
|
||||||
|
|
||||||
cd $TARGET
|
|
||||||
|
|
||||||
#docker-compose block:
|
|
||||||
|
|
||||||
# 1
|
|
||||||
docker-compose build
|
|
||||||
|
|
||||||
# 2
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# 3
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Deploy successful!"
|
|
Loading…
x
Reference in New Issue
Block a user