Dockerizeフラスコアプリ



先週、私は単純な「Hello World」フラスコアプリケーションを開始するように求められました、しかし、それはDockerコンテナに入る必要がありました.この記事では、私はどのようにこの挑戦を解決するための私のアプローチだったことを教えてくれます!

フラスコアーキテクチャと依存性


単純な「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
The . (ドット)プロジェクトのルートです.にbackend 私は適切にフラスコのアプリケーションがあります.私は建築のパターンを使った.だから、app.py これは次のとおりです.
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
このコードは、私のフラスコアプリを作成する責任があります.この記事の焦点はフラスコなどについて説明することではない.しかし、どのようにアプリケーションを構築し、それをDockerコンテナに実行します.
backend/bluprints/core 私は、私の青写真を持っていますdocumentation to know more about blueprints ), コードはBPにあります.PYとルートPy、両方の設定私のコアの青写真.最初にこのコードがあります.
from flask import Blueprint


bp = Blueprint('core', __name__)


def config(app):
    from backend.blueprints.core import routes # noqa
    app.register_blueprint(bp)
2番目のコードは以下の通りです.
from backend.blueprints.core.bp import bp


@bp.route('/')
def home():
    return "Hello World"
backend/blueprint/core/tests 私はこの青写真のテストを受けた.これは簡単なテストです.
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

Again, the focus of this article isn't to explain detailed of the Flask application, so if you have questions about how to test Flask apps please see the documentation.

Back to the root of the application, I have some files that are interesting to see!

One is the conftest.py. This file is responsible for set up pytest to run all tests in the application. Its code is:

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 簡単なファイルpytest ファイルのパターンは名前をテストしますpytest.ini コードは
[pytest]
python_files=test*.py *tests.py
他の2つのファイルはPipfile and Pipfile.lock . これらのファイルはpipenv install [package] . 私たちが後で見に行くように、我々のケースで最も重要なのはPipfile.lock それはすべての依存関係のバージョンをロックして、これらの依存関係の決定的なインストールを我々の環境に許容するので.
そして我々はDockerfile , も.このファイルはDockerイメージの作成に責任があります.このイメージは、フラスコアプリケーションでコンテナの上に使用されます.そのコードは
FROM python:3.7.1

LABEL Author="Vicente Marçal"
LABEL E-mail="[email protected]"
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
簡単な説明
FROM python:3.7.1
The FROM 自分のイメージを作成するために使用する基本イメージを定義します.この場合、私はベースイメージを使用しますpyton:3.7.1 .
LABEL Author="Vicente Marçal"
The LABEL 'sは、著者の名前、電子メールに連絡してDockerfileのバージョンのような情報を置く方法です
RUN mkdir /app
The RUN コマンドの実行に責任がありますmkdir /app これは、アプリケーションにルートと呼ばれるdirecotyrを作成します.
WORKDIR /app
The WORKDIR 作業ディレクトリを定義します/app で前に作成されますRUN 条項.
COPY Pip* /app/
The COPY はホストからコンテナへファイルをコピーし、この場合は* DockerにすべてのファイルをコピーするPip to /app/ . 注意:ディレクターのパスを完璧にすることはとても重要です/
RUN pip install --upgrade pip && \
    pip install pipenv && \
    pipenv install --dev --system --deploy --ignore-pipfile
このRUN の節のアップグレードpip , インストールpipenv そして、フラスコアプリケーション依存関係をインストールしてください.を実行するためにpipenv install フラグを指定します.--devまた、開発依存性をインストールすることを示します.--systemこれはDockerコンテナではまだ孤立した環境を持っており、VirtualEnvを作成する必要はないので、非常に重要ですpipenv まさにこれ--deploy with --ignore-pipfile通知するpipenv 使うPipfile.lock すべての依存関係をインストールするにはにPipfile.lock 私たちはあなたのバージョンロックされたすべての依存関係があります
ADD . /app
すべての依存関係のインストール後ADD ホスト上のDockerFileと同じディレクトリのすべてのファイルを追加しました/app 容器に.
obs
同じディレクトリにファイルがある.dockerignore それは.gitignore Dockerにその内容のファイルやディレクトリを無視するよう通知します.
EXPOSE 5000
この節はコンテナのポート5000を外部世界に公開します.
CMD flask run --host=0.0.0.0
最後に、節CMD ビルド後、コンテナを実行します.この場合、コマンドはflask run --host=0.0.0.0 これはホスト0.0.0.0でフラスコサーバを実行し、フラスコアプリケーションをサーバに送ります.
obs
明らかに、これは小さなテストです.あなたが生産でこれを使用する必要があるならば、それは開発環境だけで使われるフラスコサーバの代わりにUWSGIまたはGunicornのようなWSGIサーバーを走らせることを勧められます.
の使用に関するいくつかの語COPY and ADD :
Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious. Consequently, the best use for ADD is local tar file auto-extraction into the image, as in ADD rootfs.tar.xz /.

例えば https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
それは私たちのフラスコアプリをDockerizeに必要なすべてです.今、我々は我々のDockerイメージを構築して、走らせる必要があります.
ビルドするには、このDocker CLIコマンドを使用します.
docker build -t vm_docker_flask .
コマンドdocker build 旗で我々のイメージを構築します-t それは、我々のイメージでタグVMNER DockerLandフラスコを入れました、そして、最終的に、CLIの最後の部分はそうです. (ドット) 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="[email protected]"
 ---> 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 フラッグを我々の容器に入れてください-p コンテナのポート5000をホストのポート5000にバインドしてください、そして、最後に、我々のイメージの名前はdocker build コマンド.
このコマンドは私たちの端末でこの結果を示します(このコマンドはコンテナIDを返します).
33169f573b7bdf078ef8d55741ec037f2914aa78343ad96c8277854c3bcdf6b2
ここで最初のテストを行うことができます.
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コマンドは、どのコンテナが動作しているか、コンテナID、イメージ、コマンドなどの情報があれば私たちを示します.我々のケースでは、あなたが上で見ることができる方法は、Manyal ContainerRankフラスコだけです.
もう一つのテストは簡単なHTTPリクエストです.私の使用httpie application このテストで.端末の結果を見る
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
今最も重要なテスト.PyTestをコンテナに実行してテストを実行します.テストは、単にフラスコアプリによって返されたステータスコードが200 OKである場合にのみアサートされます!
これを行うには、次のdocker cliコマンドを実行します.
 docker exec my_container_flask pytest 
このDocker CLIコマンドはPyTestをMyShell ContainerRennerフラスコに対して実行します.
=========================== 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 =========================

それはすべての人々!