GNU/Linux >> Linux の 問題 >  >> Panels >> Docker

Dockerを使用してマイクロサービスをデプロイする方法

マイクロサービスとは何ですか?

マイクロサービスは、大規模なアプリケーションを構築するためのますます人気のあるアーキテクチャです。アプリケーションは、単一のモノリシックコードベースを使用するのではなく、マイクロサービスと呼ばれる小さなコンポーネントのコレクションに分割されます。このアプローチには、個々のマイクロサービスをスケーリングしたり、コードベースを理解してテストしやすくしたり、マイクロサービスごとに異なるプログラミング言語、データベース、その他のツールを使用できるようにするなど、いくつかの利点があります。

Dockerは、マイクロサービスを管理およびデプロイするための優れたツールです。各マイクロサービスは、DockerfilesおよびDockerCompose構成ファイルで指定できる個別のDockerコンテナーで実行されるプロセスにさらに分割できます。 Kubernetesなどのプロビジョニングツールと組み合わせると、各マイクロサービスを開発者チームが簡単にデプロイ、スケーリング、コラボレーションできます。このように環境を指定すると、マイクロサービスを簡単にリンクして、より大きなアプリケーションを形成することもできます。

このガイドでは、DockerとDockerComposeを使用してサンプルのマイクロサービスを構築およびデプロイする方法を示します。

始める前に

  1. まだ行っていない場合は、Linodeアカウントとコンピュートインスタンスを作成します。 Linode入門とコンピューティングインスタンスの作成ガイドをご覧ください。

  2. コンピューティングインスタンスのセットアップと保護ガイドに従って、システムを更新してください。また、タイムゾーンの設定、ホスト名の構成、制限付きユーザーアカウントの作成、SSHアクセスの強化を行うこともできます。

注 このガイドは、root以外のユーザーを対象としています。昇格された特権を必要とするコマンドには、接頭辞としてsudoが付けられます 。 sudoに慣れていない場合 コマンドを使用すると、ユーザーとグループのガイドを確認できます。

Dockerをインストールする

Docker CE(Community Edition)をインストールするには、以下のいずれかのガイドの手順に従ってください。

  • UbuntuとDebianへのDockerのインストールと使用

  • CentOSとFedoraへのDockerのインストールと使用

さらに多くのLinuxディストリビューションの詳細については、Dockerの公式ドキュメントの「Dockerエンジンのインストール」セクションを参照してください。

DockerComposeのインストール

  1. DockerComposeの最新バージョンをダウンロードします。リリースページを確認し、1.25.4を置き換えます 以下のコマンドで、バージョンが最新リリースとしてタグ付けされています :

     sudo curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    
  2. ファイルのアクセス許可を設定する:

     sudo chmod +x /usr/local/bin/docker-compose
    

環境の準備

このセクションでは、Dockerfilesを使用してDockerイメージを構成します。 Dockerfileの構文とベストプラクティスの詳細については、Dockerfilesの使用方法ガイドとDockerのDockerfileのベストプラクティスガイドを参照してください。

  1. マイクロサービス用のディレクトリを作成します:

     mkdir flask-microservice
    
  2. 新しいディレクトリ内にマイクロサービスコンポーネントのディレクトリ構造を作成します:

     cd flask-microservice
     mkdir nginx postgres web
    

NGINX

  1. 新しいnginx内 サブディレクトリで、NGINXイメージのDockerfileを作成します:

    ファイル:nginx / Dockerfile
    1
    2
    
    from nginx:alpine
    COPY nginx.conf /etc/nginx/nginx.conf
  2. nginx.confを作成します Dockerfileで参照されている:

    ファイル:/ nginx / nginx.conf
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    user  nginx;
    worker_processes 1;
    error_log  /dev/stdout info;
    error_log off;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
        use epoll;
        multi_accept on;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /dev/stdout main;
        access_log off;
        keepalive_timeout 65;
        keepalive_requests 100000;
        tcp_nopush on;
        tcp_nodelay on;
    
        server {
            listen 80;
            proxy_pass_header Server;
    
            location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
    
                # app comes from /etc/hosts, Docker added it for us!
                proxy_pass http://flaskapp:8000/;
            }
        }
    }

PostgreSQL

このマイクロサービスのPostgreSQLイメージは、公式のpostgresqlを使用します Docker Hub上のイメージなので、Dockerfileは必要ありません。

postgresで サブディレクトリ、init.sqlを作成します ファイル:

ファイル:postgres /init.sql
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
CREATE TABLE visitors (
    site_id integer,
    site_name text,
    visitor_count integer
);

ALTER TABLE visitors OWNER TO postgres;
COPY visitors (site_id, site_name, visitor_count) FROM stdin;
1 	linodeexample.com  	0
\.
注意 init.sqlの22行目 、テキストエディタがタブをスペースに変換しないことを確認してください。この行のエントリの間にタブがないと、アプリは動作しません。

ウェブ

web 画像にはFlaskアプリの例が含まれます。次のファイルをwebに追加します アプリを準備するためのディレクトリ:

  1. .python-versionを作成します Python 3.6の使用を指定するファイル:

     echo "3.6.0" >> web/.python-version
    
  2. webのDockerfileを作成します 画像:

    ファイル:web / Dockerfile
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    from python:3.6.2-slim
    RUN groupadd flaskgroup && useradd -m -g flaskgroup -s /bin/bash flask
    RUN echo "flask ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    RUN mkdir -p /home/flask/app/web
    WORKDIR /home/flask/app/web
    COPY requirements.txt /home/flask/app/web
    RUN pip install --no-cache-dir -r requirements.txt
    RUN chown -R flask:flaskgroup /home/flask
    USER flask
    ENTRYPOINT ["/usr/local/bin/gunicorn", "--bind", ":8000", "linode:app", "--reload", "--workers", "16"]
  3. web/linode.pyを作成します サンプルのアプリスクリプトを追加します:

    ファイル:web /linode.py
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    
    from flask import Flask
    import logging
    import psycopg2
    import redis
    import sys
    
    app = Flask(__name__)
    cache = redis.StrictRedis(host='redis', port=6379)
    
    # Configure Logging
    app.logger.addHandler(logging.StreamHandler(sys.stdout))
    app.logger.setLevel(logging.DEBUG)
    
    def PgFetch(query, method):
    
        # Connect to an existing database
        conn = psycopg2.connect("host='postgres' dbname='linode' user='postgres' password='linode123'")
    
        # Open a cursor to perform database operations
        cur = conn.cursor()
    
        # Query the database and obtain data as Python objects
        dbquery = cur.execute(query)
    
        if method == 'GET':
            result = cur.fetchone()
        else:
            result = ""
    
        # Make the changes to the database persistent
        conn.commit()
    
        # Close communication with the database
        cur.close()
        conn.close()
        return result
    
    @app.route('/')
    def hello_world():
        if cache.exists('visitor_count'):
            cache.incr('visitor_count')
            count = (cache.get('visitor_count')).decode('utf-8')
            update = PgFetch("UPDATE visitors set visitor_count = " + count + " where site_id = 1;", "POST")
        else:
            cache_refresh = PgFetch("SELECT visitor_count FROM visitors where site_id = 1;", "GET")
            count = int(cache_refresh[0])
            cache.set('visitor_count', count)
            cache.incr('visitor_count')
            count = (cache.get('visitor_count')).decode('utf-8')
        return 'Hello Linode!  This page has been viewed %s time(s).' % count
    
    @app.route('/resetcounter')
    def resetcounter():
        cache.delete('visitor_count')
        PgFetch("UPDATE visitors set visitor_count = 0 where site_id = 1;", "POST")
        app.logger.debug("reset visitor count")
        return "Successfully deleted redis and postgres counters"
  4. requirements.txtを追加します 必要なPython依存関係を持つファイル:

    ファイル:web /requirements.txt
    1
    2
    3
    4
    
    flask
    gunicorn
    psycopg2-binary
    redis

Docker Compose

Docker Composeは、コンテナとその構成設定の間の接続を定義するために使用されます。

docker-compose.ymlを作成します flask-microservice内のファイル ディレクトリを作成し、以下を追加します:

ファイル:docker -compose.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
version: '3'
services:
 # Define the Flask web application
 flaskapp:

   # Build the Dockerfile that is in the web directory
   build: ./web

   # Always restart the container regardless of the exit status; try and restart the container indefinitely
   restart: always

   # Expose port 8000 to other containers (not to the host of the machine)
   expose:
     - "8000"

   # Mount the web directory within the container at /home/flask/app/web
   volumes:
     - ./web:/home/flask/app/web

   # Don't create this container until the redis and postgres containers (below) have been created
   depends_on:
     - redis
     - postgres

   # Link the redis and postgres containers together so they can talk to one another
   links:
     - redis
     - postgres

   # Pass environment variables to the flask container (this debug level lets you see more useful information)
   environment:
     FLASK_DEBUG: 1

   # Deploy with three replicas in the case one of the containers fails (only in Docker Swarm)
   deploy:
     mode: replicated
     replicas: 3

 # Define the redis Docker container
 redis:

   # use the redis:alpine image: https://hub.docker.com/_/redis/
   image: redis:alpine
   restart: always
   deploy:
     mode: replicated
     replicas: 3

 # Define the redis NGINX forward proxy container
 nginx:

   # build the nginx Dockerfile: http://bit.ly/2kuYaIv
   build: nginx/
   restart: always

   # Expose port 80 to the host machine
   ports:
     - "80:80"
   deploy:
     mode: replicated
     replicas: 3

   # The Flask application needs to be available for NGINX to make successful proxy requests
   depends_on:
     - flaskapp

 # Define the postgres database
 postgres:
   restart: always
   # Use the postgres alpine image: https://hub.docker.com/_/postgres/
   image: postgres:alpine

   # Mount an initialization script and the persistent postgresql data volume
   volumes:
     - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
     - ./postgres/data:/var/lib/postgresql/data

   # Pass postgres environment variables
   environment:
     POSTGRES_PASSWORD: linode123
     POSTGRES_DB: linode

   # Expose port 5432 to other Docker containers
   expose:
     - "5432"

マイクロサービスをテストする

  1. Docker Composeを使用してすべてのイメージをビルドし、マイクロサービスを開始します:

    cd flask-microservice/ && docker-compose up
    

    ターミナルですべてのサービスが開始されていることを確認する必要があります。

  2. 新しいターミナルウィンドウを開き、サンプルアプリケーションにリクエストを送信します。

    curl localhost
    
    Hello Linode! This page has been viewed 1 time(s).
  3. ページヒットカウンターをリセットします:

    curl localhost/resetcounter
    
    Successfully deleted redis and postgres counters
  4. Docker Composeが開始されたターミナルウィンドウに戻り、標準の出力ログを表示します。

    flaskapp_1  | DEBUG in linode [/home/flask/app/web/linode.py:56]:
    flaskapp_1  | reset visitor count

本番環境でのコンテナの使用:ベストプラクティス

サンプルのマイクロサービスで使用されているコンテナーは、本番環境でコンテナーを使用するための次のベストプラクティスを示すことを目的としています。

コンテナは次のようになります:

  1. 一時的 :最小限のセットアップと構成で、コンテナーの停止、破棄、再構築、および再デプロイが簡単にできる必要があります。

    Flaskマイクロサービスはこの理想的な例です。マイクロサービス全体は、DockerComposeを使用して起動または停止できます。コンテナの実行後に追加の構成は必要ないため、アプリケーションを簡単に変更できます。

  2. 使い捨て :理想的には、より大きなアプリケーション内の単一のコンテナーは、アプリケーションのパフォーマンスに影響を与えることなく失敗できる必要があります。 restart: on-failureの使用 docker-compose.ymlのオプション ファイルは、レプリカカウントを持っているだけでなく、サンプルのマイクロサービスの一部のコンテナが、エンドユーザーに悪影響を与えることなく、Webアプリケーションを提供しながら正常に失敗することを可能にします。

    注 レプリカカウントディレクティブは、この構成がこのガイドでカバーされていないaDockerSwarmの一部として展開されている場合にのみ有効になります。
  3. すぐに開始 :Dockerファイルでの追加のインストール手順の回避、不要な依存関係の削除、再利用可能なターゲットイメージの構築は、Docker内で初期化時間が短いWebアプリケーションを作成する上で最も重要な3つの手順です。サンプルアプリケーションでは、初期化時間を最小限に抑えるために、短く簡潔なビルド済みのDockerfileを使用しています。

  4. すばやく停止docker kill --signal=SIGINT {APPNAME}であることを検証します アプリケーションを正常に停止します。これにより、再起動条件とレプリカ条件とともに、コンテナに障害が発生した場合に、コンテナを効率的にオンラインに戻すことができます。

  5. 軽量 :アプリケーションの構築と実行に必要なすべてのユーティリティを提供する最小のベースコンテナを使用します。多くのDockerイメージは、Dockerイメージでわずか5MBを占める軽量でシンプルなLinuxディストリビューションであるAlpineLinuxに基づいています。小さなディストロを使用すると、ネットワークと運用のオーバーヘッドが節約され、コンテナのパフォーマンスが大幅に向上します。サンプルアプリケーションでは、該当する場合はアルパインイメージ(NGINX、Redis、PostgreSQL)を使用し、Gunicorn/Flaskアプリケーションにはpython-slimベースイメージを使用します。

  6. ステートレス :一時的なものであるため、コンテナは通常、状態を維持するべきではありません。マイクロサービスのPostgreSQLデータストアの場合と同様に、アプリケーションの状態は別の永続的なデータボリュームに保存する必要があります。 Redis Key-Valueストアはコンテナー内のデータを維持しますが、このデータはアプリケーションクリティカルではありません。コンテナが応答できない場合、Redisストアはデータベースに正常にフェールバックします。

  7. ポータブル :コンテナランタイムに必要なアプリの依存関係はすべて、ローカルで利用可能である必要があります。サンプルのマイクロサービスの依存関係と起動スクリプトはすべて、各コンポーネントのディレクトリに保存されています。これらはバージョン管理にチェックインできるため、アプリケーションの共有と展開が簡単になります。

  8. モジュラー :各コンテナには、1つの責任と1つのプロセスが必要です。このマイクロサービスでは、主要なプロセス(NGINX、Python、Redis、PostgreSQL)のそれぞれが個別のコンテナーにデプロイされます。

  9. ロギング :すべてのコンテナはSTDOUTにログを記録する必要があります 。この均一性により、単一のストリームですべてのプロセスのログを簡単に表示できます。

  10. 回復力 :サンプルアプリケーションは、何らかの理由でコンテナが終了した場合にコンテナを再起動します。これにより、メンテナンス期間中であっても、Dockerizedアプリケーションに高可用性とパフォーマンスを提供できます。

詳細情報

このトピックの詳細については、次のリソースを参照してください。これらは有用であることを期待して提供されていますが、外部でホストされている資料の正確性や適時性を保証することはできません。

  • マイクロサービスの例のGithubリポジトリ
  • コンテナを使用したマイクロサービスアーキテクチャの構築

Docker
  1. Debian10でDockerを使用してダイナミックDNSサーバーをデプロイする方法

  2. Ubuntu20.04LTSでNginxを使用してModsecurityをデプロイする方法

  3. Dockerを使用してJenkinsをインストールする方法

  1. ランチャーでアプリをデプロイする方法

  2. LinodeにDockerを使用してnginxコンテナをデプロイする方法

  3. PostgreSQLをDockerコンテナとしてデプロイする方法

  1. DockerにNGINXリバースプロキシをデプロイする方法

  2. Dockerを使用してMongoDBをデプロイおよび管理する方法

  3. DockerとNGINXとAPIプロキシを使用してReactアプリを本番環境にデプロイする方法