На прошлой неделе мне было брошено вызов, чтобы начать простое «Hello World» приложение для колбы, но это необходимо для запуска в контейнер докера. В этой статье я покажу вам, как был мой подход, чтобы решить эту проблему!
Хотя простой «Hello World», который я работал с лучшими практиками архитектуры. У меня была следующая структура каталога:
. ├── backend │ ├── app.py │ ├── blueprints │ │ ├── core │ │ │ ├── bp.py │ │ │ ├── __init__.py │ │ │ ├── routes.py │ │ │ └── tests │ │ │ └── test_bp_core.py │ │ └── __init__.py │ └── __init__.py ├── conftest.py ├── Dockerfile ├── .dockerignore ├── .gitignore ├── Pipfile ├── Pipfile.lock ├── pytest.ini └── README.md
from flask import Flask def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = 'My_Top_Secert_Key' # Blueprint from backend.blueprints.core import bp as bp_core bp_core.config(app) return app
from flask import Blueprint bp = Blueprint('core', __name__) def config(app): from backend.blueprints.core import routes # noqa app.register_blueprint(bp)
from backend.blueprints.core.bp import bp @bp.route('/') def home(): return "Hello World"
import pytest from flask import url_for @pytest.fixture def resp(client): return client.get(url_for('core.home')) def test_bp_home_status_code_ok(resp): assert resp.status_code == 200
Опять же, в центре внимания этой статьи не следует объяснять подробную информацию о приложении Flask, поэтому, если у вас есть вопросы о том, как тестировать приложения Flask, пожалуйста, смотрите Документация Отказ
Вернуться к корню приложения, у меня есть некоторые файлы, которые интересны!
Один из них Conftest.py
Отказ Этот файл отвечает за настройки pteest
Чтобы запустить все тесты в приложении. Его код:
import pytest from backend.app import create_app @pytest.fixture def app(): app = create_app() return app @pytest.fixture def client(app): with app.test_client() as c: yield c
Другое – это Pytest.ini
Простой файл, который сообщает pteest
Шаблон файлов проверяет имена, в нашем случае Pytest.ini
код:
[pytest] python_files=test*.py *tests.py
Две другие файлы – Pipfile
и Pipfile.lock.lock.lock
. Эти файлы создаются или обновлены командой Pipenv Установите [Пакет]
Отказ Как мы увидим позже, самым важным в нашем случае является Pipfile.lock
Поскольку он блокирует версию всех зависимостей и позволяет определять детерминированную установку этих зависимостей в нашей среде.
И у нас есть Dockerfile
, слишком. Этот файл отвечает за создание докера изображения. Это изображение будет использоваться для поднятия контейнера с приложением колба. Его код:
FROM python:3.7.1 LABEL Author="Vicente Marçal" LABEL E-mail="vicente.marcal@gmail.com" LABEL version="0.0.1b" ENV PYTHONDONTWRITEBYTECODE 1 ENV FLASK_APP "backend/app.py" ENV FLASK_ENV "development" ENV FLASK_DEBUG True RUN mkdir /app WORKDIR /app COPY Pip* /app/ RUN pip install --upgrade pip && \ pip install pipenv && \ pipenv install --dev --system --deploy --ignore-pipfile ADD . /app EXPOSE 5000 CMD flask run --host=0.0.0.0
Краткий объяснение об этом:
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘То’, {‘code’: ‘ОТ’}, ‘Определите базовое изображение, которое будет использоваться для создания моего изображения. В этом случае я использую базовое изображение’, {‘code’: ‘Python: 3.7.1’}, ‘.’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘То’, {‘code’: ‘МЕТКА’}, ‘- это способ поставить некоторую информацию, как имя автора, электронная почта для контакта и версия DockerFile’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘То’, {‘code’: ‘БЕЖАТЬ’}, ‘отвечает за выполнение команд, в этом случае то’, {‘code’: ‘mkdir/app.’}, ‘которые создают каталог, называемое приложением в корне.’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘То’, {‘code’: ‘Рабочий’}, ‘Определяет рабочий каталог, в этом случае мой’, {‘code’: ‘/приложение’}, ‘создан предыдущий в’, {‘code’: ‘БЕЖАТЬ’}, ‘пункт.’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘То’, {‘code’: ‘Скопировать’}, ‘зависит от копирования файлов с хоста в контейнер, в этом случае с’, {‘code’: ‘*’}, ‘сообщить Docker, чтобы скопировать все файлы начать с’, {‘code’: ‘Пипс’}, ‘к’, {‘code’: ‘/приложение/’}, ‘. Обратите внимание: очень важно доработать путь директора с’, {‘code’: ‘/’}]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘Этот’, {‘code’: ‘БЕЖАТЬ’}, ‘пункт делает модернизацию’, {‘code’: ‘пипс’}, ‘, установить’, {‘code’: ‘пиронв’}, ‘и установите сквозные приложенные зависимости. Для установки колбежных зависимостей использовался’, {‘code’: ‘Установка Pipenv’}, ‘С некоторыми флагами:’]}
- {‘dt’: {‘code’: ‘–dev.’}}
- {‘dd’: ‘это также указывает на установку зависимостей разработки;’}
- {‘dt’: {‘code’: ‘–система’}}
- {‘dd’: [‘Это очень важно, потому что в докер контейнер у нас есть изолированная среда, и не нужно создавать виртуальнв, Этот флаг сообщает’, {‘code’: ‘пиронв’}, ‘именно это;’]}
- {‘dt’: [{‘code’: ‘–развертывать’}, ‘с’, {‘code’: ‘- свет-Pipfile’}]}
- {‘dd’: [‘сообщить’, {‘code’: ‘пиронв’}, ‘использовать’, {‘code’: ‘Pipfile.lock.lock.lock’}, ‘Чтобы установить все зависимости. в’, {‘code’: ‘Pipfile.lock.lock.lock’}, ‘У нас есть все зависимости с вашими версиями заблокирован’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘После установки всех зависимостей с предложением’, {‘code’: ‘ДОБАВЛЯТЬ’}, ‘Добавлены все файлы одного каталога, где находится DockerFile на хосте’, {‘code’: ‘/приложение’}, ‘на контейнере.’]}
- {‘dt’: ‘ABS:’}
- {‘dd’: [‘В том же каталоге есть файл называется’, {‘code’: ‘.dockerignore.’}, ‘что вроде’, {‘code’: ‘.gitignore.’}, ‘Inform Docker, чтобы игнорировать файлы и каталоги в своем содержании.’]}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: ‘Этот пункт обнажает порт 5000 контейнера к внешнему миру.’}
- {‘dt’: {‘pre’: ”}}
- {‘dd’: [‘Окончательно, оговорка’, {‘code’: ‘CMD’}, ‘Выполните команды после сборки и вверх контейнера. В этом случае команда является’, {‘code’: ‘Flask Run.0.0.0.’}, ‘которые выполняют сервер Flask в Host 0.0.0.0 и серверы нашего приложения Flask.’]}
- {‘dt’: ‘ABS:’}
- {‘dd’: ‘Очевидно, это небольшой тест. Если вам нужно использовать это в производстве, рекомендуется запустить сервер WSGI, как UWSGI или Gunicorn вместо сервера Flask, который используется только в среде разработки.’}
Некоторые слова о использовании Скопировать
и Добавить
:
Реф.: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
Это все, что нам нужно подключить наше приложение для колбы. Теперь нам нужно построить и запустить наш документ докера.
Чтобы построить мы используем эту команду Docker CLI:
docker build -t vm_docker_flask .
Команда Docker Build
построит наш образ, с флагом -t
Это положил тег vm_docker_flask На нашем образе и, наконец, последняя часть CLI – Отказ
(DOT), который сообщает Docker, что DockerFile находится в текущем каталоге.
Эта команда показывает нам этот результат в нашем терминале:
Sending build context to Docker daemon 29.18kB Step 1/15 : FROM python:3.7.1 ---> 1e80caffd59e Step 2/15 : LABEL Author="Vicente Marçal" ---> Running in a7975e93672a Removing intermediate container a7975e93672a ---> 448662ef63d8 Step 3/15 : LABEL E-mail="vicente.marcal@gmail.com" ---> Running in 75f6319066de Removing intermediate container 75f6319066de ---> 0898192a03f7 Step 4/15 : LABEL version="0.0.1b" ---> Running in defb5aee2083 Removing intermediate container defb5aee2083 ---> 02042247ded0 Step 5/15 : ENV PYTHONDONTWRITEBYTECODE 1 ---> Running in 5e9124dfa05c Removing intermediate container 5e9124dfa05c ---> c35cd3ecc42f Step 6/15 : ENV FLASK_APP "backend/app.py" ---> Running in ea58e08644ad Removing intermediate container ea58e08644ad ---> f2fb780d29fc Step 7/15 : ENV FLASK_ENV "development" ---> Running in f72976410ba2 Removing intermediate container f72976410ba2 ---> bb444664e3b0 Step 8/15 : ENV FLASK_DEBUG True ---> Running in e18257443538 Removing intermediate container e18257443538 ---> a2bbca32f540 Step 9/15 : RUN mkdir /app ---> Running in ebbcc284fe40 Removing intermediate container ebbcc284fe40 ---> 7fb8c7fac9f8 Step 10/15 : WORKDIR /app ---> Running in c76604d10578 Removing intermediate container c76604d10578 ---> 074aa15fee4c Step 11/15 : COPY Pip* /app/ ---> 554f403d7b11 Step 12/15 : RUN pip install --upgrade pip && pip install pipenv && pipenv install --dev --system --deploy --ignore-pipfile ---> Running in 08faec42b7d5 Collecting pip Downloading https://files.pythonhosted.org/packages/d8/f3/413bab4ff08e1fc4828dfc59996d721917df8e8583ea85385d51125dceff/pip-19.0.3-py2.py3-none-any.whl (1.4MB) Installing collected packages: pip Found existing installation: pip 18.1 Uninstalling pip-18.1: Successfully uninstalled pip-18.1 Successfully installed pip-19.0.3 Collecting pipenv Downloading https://files.pythonhosted.org/packages/13/b4/3ffa55f77161cff9a5220f162670f7c5eb00df52e00939e203f601b0f579/pipenv-2018.11.26-py3-none-any.whl (5.2MB) Requirement already satisfied: pip>=9.0.1 in /usr/local/lib/python3.7/site-packages (from pipenv) (19.0.3) Collecting virtualenv-clone>=0.2.5 (from pipenv) Downloading https://files.pythonhosted.org/packages/e3/d9/d9c56deb483c4d3289a00b12046e41428be64e8236fa210111a1f57cc42d/virtualenv_clone-0.5.1-py2.py3-none-any.whl Collecting virtualenv (from pipenv) Downloading https://files.pythonhosted.org/packages/33/5d/314c760d4204f64e4a968275182b7751bd5c3249094757b39ba987dcfb5a/virtualenv-16.4.3-py2.py3-none-any.whl (2.0MB) Collecting certifi (from pipenv) Downloading https://files.pythonhosted.org/packages/9f/e0/accfc1b56b57e9750eba272e24c4dddeac86852c2bebd1236674d7887e8a/certifi-2018.11.29-py2.py3-none-any.whl (154kB) Requirement already satisfied: setuptools>=36.2.1 in /usr/local/lib/python3.7/site-packages (from pipenv) (40.6.2) Installing collected packages: virtualenv-clone, virtualenv, certifi, pipenv Successfully installed certifi-2018.11.29 pipenv-2018.11.26 virtualenv-16.4.3 virtualenv-clone-0.5.1 Installing dependencies from Pipfile.lock (9a5a3a)… Removing intermediate container 08faec42b7d5 ---> 740ed1329305 Step 13/15 : ADD . /app ---> 3551608282e2 Step 14/15 : EXPOSE 5000 ---> Running in 07b57fe6a5e7 Removing intermediate container 07b57fe6a5e7 ---> 2e07658bbae8 Step 15/15 : CMD flask run --host=0.0.0.0 ---> Running in bdf7404770f6 Removing intermediate container bdf7404770f6 ---> cf7d3ee68072 Successfully built cf7d3ee68072 Successfully tagged vm_docker_flask:latest
После этого нам нужно запустить наш контейнер. Последующее команду Docker CLI делает магию:
docker run -d --name my_container_flask -p 5000:5000 vm_docker_flask
Команда Docker Run
Запускает наш контейнер, флаг -d
сообщить Docker, который работает в фоновом режиме, флаг --name
поставить my_container_flask в наш контейнер, флаг -П
Свяжите порт 5000 контейнера к порту 5000 хоста и, в конце, это название нашего изображения, встроенного в Docker Build
команда.
Эта команда показывает нам этот результат в нашем терминале (или аналогично, потому что эта команда возвращает идентификатор контейнера):
33169f573b7bdf078ef8d55741ec037f2914aa78343ad96c8277854c3bcdf6b2
Теперь мы можем сделать наш первый тест, посмотреть, работает ли наш контейнер, для этого мы выполняем команду Docker CLI так:
pythonprojects/docker_flask_app [ docker container ps ] CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 880a5b59f2aa vm_docker_flask "/bin/sh -c 'flask r…" 15 minutes ago Up 15 minutes 0.0.0.0:5000->5000/tcp my_container_flask
Эта команда Docker CLI показывает нам, если наши контейнеры работают и их информация, как идентификатор контейнера, изображение, команда и так далее. В нашем случае только my_container_flask Как вы можете увидеть выше.
Еще один тест, который мы можем сделать, это простой HTTP-запрос. Я использую httpie-приложение В этом тесте. Смотрите результат терминала:
pythonprojects/docker_flask_app [ http 0.0.0.0:5000 ] HTTP/1.0 200 OK Content-Length: 11 Content-Type: text/html; charset=utf-8 Date: Tue, 05 Mar 2019 18:17:24 GMT Server: Werkzeug/0.14.1 Python/3.7.1 Hello World
Теперь самый важный тест. Мы выполняем Pтойцу в наш контейнер, чтобы запустить тесты против нашей колбы. Тест просто прост только утверждение, если код состояния, возвращаемый приложением Flask, это 200 ОК!
Для этого мы выполняем команду Follow Docker CLI:
docker exec my_container_flask pytest
Эта команда Docker CLI работает в Pteest против my_container_flask, и если все в порядке, у нас есть этот клеммный результат:
=========================== test session starts ============================ platform linux -- Python 3.7.1, pytest-4.3.0, py-1.8.0, pluggy-0.9.0 rootdir: /app, inifile: pytest.ini plugins: sugar-0.9.2, flask-0.14.0 collected 1 item backend/blueprints/core/tests/test_bp_core.py . [100%] ========================= 1 passed in 0.06 seconds =========================
Это все люди !!
Оригинал: “https://dev.to/riverfount/dockerize-a-flask-app-17ag”