Skip to content

Commit db982d5

Browse files
committed
Initial commit
0 parents  commit db982d5

35 files changed

+990
-0
lines changed

01_docker_compose/README.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Проектное задание: Docker-compose
2+
3+
Приступим к улучшению сервиса в области DevOps. Настройте запуск всех компонентов системы — Django, Nginx и Postgresql — с использованием docker-compose.
4+
5+
Для упрощения выполнения задания мы подготовили проект, где настроена работа связки Django + uWSGI + Nginx + Docker. Вы можете взять его за основу, но его придётся дополнительно доработать, чтобы подключить Postgres, а также устранить мелкие ошибки в конфигурировании Django: например, `debug = True` или отсутствие настроек чтения переменных окружения.
6+
7+
Сама заготовка уже показывает админку с примером одного метода API. Однако статика не собирается, миграций нет, конфиги Nginx, uWSGI и Docker, возможно, придётся подправить.
8+
9+
Если вы считаете, что всё нужно сделать по-другому, воспользуйтесь пустой заготовкой проекта и напишите его самостоятельно.
10+
11+
**Требования к работе:**
12+
13+
- Напишите dockerfile для Django.
14+
- Для настройки Nginx можно пользоваться наработками из этой темы, но ревьюеры будут запускать ваше решение. Перед сдачей проекта убедитесь, что всё работает правильно.
15+
- Уберите версию Nginx из заголовков. Версии любого ПО лучше скрывать от посторонних глаз, чтобы вашу админку случайно не взломали. Найдите необходимую настройку в официальной документации и проверьте, что она работает корректно. Убедиться в этом можно с помощью «Инструментов разработчика» в браузере.
16+
- Отдавайте статические файлы Django через Nginx, чтобы не нагружать сервис дополнительными запросами. Перепишите `location` таким образом, чтобы запросы на `/admin` шли без поиска статического контента. То есть, минуя директиву `try_files $uri @backend;`.
17+
18+
**Подсказки и советы:**
19+
20+
- Теории на платформе должно быть достаточно для понимания принципов конфигурирования. Если у вас появятся какие-то вопросы по параметрам, ищите ответы [в официальной документации](https://nginx.org/ru/).
21+
- Для выполнения задачи про `/admin` нужно посмотреть порядок поиска `location`.
22+
- Для работы со статикой нужно подумать, как залить данные в файловую систему контейнера с Nginx.
23+
- Для задания дана базовая структура, которой можно пользоваться.
24+
- При настройке docker-compose важно проверять пути до папок. Большинство проблем связанно именно с этим.

01_docker_compose/empty_project/Dockerfile

Whitespace-only changes.

01_docker_compose/empty_project/app/__init__.py

Whitespace-only changes.

01_docker_compose/empty_project/docker-compose.yml

Whitespace-only changes.

01_docker_compose/empty_project/nginx/nginx.conf

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FROM python:3.10
2+
3+
WORKDIR /opt/app
4+
5+
ENV PYTHONDONTWRITEBYTECODE 1
6+
ENV PYTHONUNBUFFERED 1
7+
ENV UWSGI_PROCESSES 1
8+
ENV UWSGI_THREADS 16
9+
ENV UWSGI_HARAKIRI 240
10+
ENV DJANGO_SETTINGS_MODULE 'example.settings'
11+
12+
COPY run_uwsgi.sh run_uwsgi.sh
13+
COPY requirements.txt requirements.txt
14+
COPY uwsgi/uwsgi.ini uwsgi.ini
15+
16+
RUN mkdir -p /var/www/static/ \
17+
&& mkdir -p /var/www/media/ \
18+
&& mkdir -p /opt/app/static/ \
19+
&& mkdir -p /opt/app/media/ \
20+
&& pip install --upgrade pip \
21+
&& pip install -r requirements.txt
22+
23+
COPY . .
24+
25+
EXPOSE 8000
26+
27+
ENTRYPOINT ["uwsgi", "--strict", "--ini", "uwsgi.ini"]

01_docker_compose/simple_project/app/example/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for example project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
15+
16+
application = get_asgi_application()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""
2+
Django settings for example project.
3+
4+
Generated by 'django-admin startproject' using Django 4.0.4.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/topics/settings/
8+
9+
For the full list of settings and their values, see
10+
https://docs.djangoproject.com/en/4.0/ref/settings/
11+
"""
12+
13+
from pathlib import Path
14+
15+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16+
BASE_DIR = Path(__file__).resolve().parent.parent
17+
18+
19+
# Quick-start development settings - unsuitable for production
20+
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
21+
22+
# SECURITY WARNING: keep the secret key used in production secret!
23+
SECRET_KEY = 'django-insecure-@k04vsjy@qv3m573&94kgq_kjj@lad^^d%hr_o2sk!a6+c3ne9'
24+
25+
# SECURITY WARNING: don't run with debug turned on in production!
26+
DEBUG = True
27+
28+
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '[::1]']
29+
30+
31+
# Application definition
32+
33+
INSTALLED_APPS = [
34+
'django.contrib.admin',
35+
'django.contrib.auth',
36+
'django.contrib.contenttypes',
37+
'django.contrib.sessions',
38+
'django.contrib.messages',
39+
'django.contrib.staticfiles',
40+
'movies',
41+
]
42+
43+
MIDDLEWARE = [
44+
'django.middleware.security.SecurityMiddleware',
45+
'django.contrib.sessions.middleware.SessionMiddleware',
46+
'django.middleware.common.CommonMiddleware',
47+
'django.middleware.csrf.CsrfViewMiddleware',
48+
'django.contrib.auth.middleware.AuthenticationMiddleware',
49+
'django.contrib.messages.middleware.MessageMiddleware',
50+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
51+
]
52+
53+
ROOT_URLCONF = 'example.urls'
54+
55+
TEMPLATES = [
56+
{
57+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
58+
'DIRS': [],
59+
'APP_DIRS': True,
60+
'OPTIONS': {
61+
'context_processors': [
62+
'django.template.context_processors.debug',
63+
'django.template.context_processors.request',
64+
'django.contrib.auth.context_processors.auth',
65+
'django.contrib.messages.context_processors.messages',
66+
],
67+
},
68+
},
69+
]
70+
71+
WSGI_APPLICATION = 'example.wsgi.application'
72+
73+
74+
# Database
75+
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
76+
77+
DATABASES = {
78+
'default': {
79+
'ENGINE': 'django.db.backends.sqlite3',
80+
'NAME': BASE_DIR / 'db.sqlite3',
81+
}
82+
}
83+
84+
85+
# Password validation
86+
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
87+
88+
AUTH_PASSWORD_VALIDATORS = [
89+
{
90+
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91+
},
92+
{
93+
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94+
},
95+
{
96+
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97+
},
98+
{
99+
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100+
},
101+
]
102+
103+
104+
# Internationalization
105+
# https://docs.djangoproject.com/en/4.0/topics/i18n/
106+
107+
LANGUAGE_CODE = 'en-us'
108+
109+
TIME_ZONE = 'UTC'
110+
111+
USE_I18N = True
112+
113+
USE_TZ = True
114+
115+
116+
# Static files (CSS, JavaScript, Images)
117+
# https://docs.djangoproject.com/en/4.0/howto/static-files/
118+
119+
STATIC_URL = 'static/'
120+
121+
# Default primary key field type
122+
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
123+
124+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""example URL Configuration
2+
3+
The `urlpatterns` list routes URLs to views. For more information please see:
4+
https://docs.djangoproject.com/en/4.0/topics/http/urls/
5+
Examples:
6+
Function views
7+
1. Add an import: from my_app import views
8+
2. Add a URL to urlpatterns: path('', views.home, name='home')
9+
Class-based views
10+
1. Add an import: from other_app.views import Home
11+
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12+
Including another URLconf
13+
1. Import the include() function: from django.urls import include, path
14+
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15+
"""
16+
from django.contrib import admin
17+
from django.urls import include, path
18+
19+
urlpatterns = [
20+
path('admin/', admin.site.urls),
21+
path('api/', include('movies.api.urls')),
22+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
WSGI config for example project.
3+
4+
It exposes the WSGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.wsgi import get_wsgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
15+
16+
application = get_wsgi_application()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
import os
4+
import sys
5+
6+
7+
def main():
8+
"""Run administrative tasks."""
9+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
10+
try:
11+
from django.core.management import execute_from_command_line
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
18+
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == '__main__':
22+
main()

01_docker_compose/simple_project/app/movies/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

01_docker_compose/simple_project/app/movies/api/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.urls import path, include
2+
3+
4+
urlpatterns = [
5+
path('v1/', include('movies.api.v1.urls')),
6+
]

01_docker_compose/simple_project/app/movies/api/v1/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.urls import path
2+
3+
from movies.api.v1 import views
4+
5+
urlpatterns = [
6+
path('movies/', views.api),
7+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.http import HttpResponse
2+
3+
4+
def api(request):
5+
return HttpResponse("My best API")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class MoviesConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'movies'

01_docker_compose/simple_project/app/movies/migrations/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.db import models
2+
3+
# Create your models here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.shortcuts import render
2+
3+
# Create your views here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
django==4.0.4
2+
uwsgi==2.0.20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
chown www-data:www-data /var/log
6+
7+
uwsgi --strict --ini /etc/app/uwsgi.ini
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[uwsgi]
2+
socket = :8000
3+
protocol = http
4+
5+
uid = www-data
6+
gid = www-data
7+
8+
master = true
9+
no-orphans = true
10+
11+
die-on-term = true
12+
single-interpreter = true
13+
14+
lazy-apps = true
15+
16+
processes = $(UWSGI_PROCESSES)
17+
threads = $(UWSGI_THREADS)
18+
enable-threads = true
19+
20+
max-requests = 5000
21+
22+
harakiri = $(UWSGI_HARAKIRI)
23+
harakiri-verbose = true
24+
25+
vacuum = true
26+
27+
reload-mercy = 10
28+
29+
chdir = /opt/app
30+
31+
wsgi-file = example/wsgi.py
32+
33+
post-buffering = 1048576
34+
buffer-size = 65535
35+
static-map = /static=/var/wwww/static
36+
static-map = /media=/var/wwww/media
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
server {
2+
listen 80 default_server;
3+
listen [::]:80 default_server;
4+
server_name _; # Обслуживает любой хост
5+
6+
root /data;
7+
8+
location @backend {
9+
proxy_pass http://service:8000;
10+
}
11+
12+
location ~* \.(?:jpg|jpeg|gif|png|ico|css|js)$ {
13+
log_not_found off;
14+
expires 90d;
15+
}
16+
17+
location / {
18+
try_files $uri @backend;
19+
}
20+
21+
error_page 404 /404.html;
22+
23+
# redirect server error pages to the static page /50x.html
24+
#
25+
error_page 500 502 503 504 /50x.html;
26+
location = /50x.html {
27+
root html;
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Static page</title>
6+
</head>
7+
<body>
8+
I'm static
9+
</body>
10+
</html>

0 commit comments

Comments
 (0)