20210411のdockerに関する記事は9件です。

Dockerについてのまとめ

はじめに この1年と少しDockerを使用してきましたが、正直まだ基本的なところで理解できていないところもありました。 なので改めてドキュメントを1から読み、まとめてみました。 主に以下のドキュメントを読み、まとめています。説明の順番や内容等は一部ドキュメントと異なる部分があります。 Dockerの概要と使用することで得られるメリット Dockerとはアプリケーションを開発、デプロイ、運用するためのオープンなプラットフォームです。 Dockerを使用することで、アプリケーションをインフラから分離することができ、アプリケーションの開発をスムーズに進めることができます。 Dockerを使用することで、アプリケーションを管理するのと同じようにインフラの管理をすることができます。 Dockerが提供する機能について Dockerは、アプリケーションをパッケージ化し、コンテナと呼ばれるゆるやかに隔離された環境で実行する機能を提供します。この隔離された環境とセキュリティにより、特定のホスト上で多くのコンテナを同時に実行することができます。 コンテナは軽量で、アプリケーションの実行に必要なものがすべて含まれているため、ホストに現在インストールされているものに頼る必要がありません。作業中にコンテナを簡単に共有することができ、共有した全員が同じ方法で動作する同じコンテナを手に入れることができます。 Docker社のコンテナベースのプラットフォームは、移植性の高いワークロードを可能にします。Dockerコンテナは、開発者のローカルラップトップ、データセンター内の物理マシンや仮想マシン、クラウド事業者、あるいはそれらが混在する環境でも実行することができます。 Dockerが使用している技術について Dockerは、プログラミング言語「Go」で書かれており、Linuxカーネルのいくつかの機能を利用して機能を実現しています。Dockerは、namaspaceと呼ばれる技術を用いて、コンテナと呼ばれる隔離された作業空間を提供しており、コンテナを実行すると、Dockerはそのコンテナのための名前空間のセットを作成します。 Dockerのアーキテクチャについて Dockerはクライアント・サーバー型のアーキテクチャを採用しています。 DockerクライアントはDockerデーモンと対話し、デーモンはDockerコンテナの構築、実行、配布などの処理を行います。 Dockerクライアントとデーモンは同じシステム上で動作しますが、DockerクライアントをリモートのDockerデーモンに接続することもできます。Dockerクライアントとデーモンは、REST APIを使って、UNIXソケットやネットワークインターフェースを介して通信し、もうひとつのDockerクライアントはDocker Composeでこれはコンテナのセットで構成されたアプリケーションを扱うことができます。 アーキテクチャのイメージに関しては、以下のDockerのドキュメントの図が分かりやすいです。 主な登場人物(用語) Docker daemaon (dockerd) Dockerデーモン(dockerd)は、Docker APIリクエストをリッスンし、イメージ、コンテナ、ネットワーク、ボリュームなどのDockerオブジェクトを管理します。 Docker client (docker) Dockerクライアント(docker)は、DockerユーザーがDockerと対話するための主な手段です。docker runなどのコマンドを使用すると、クライアントはこれらのコマンドをdockerdに送信し、dockerdがそれを実行します。dockerコマンドはDocker APIを使用します。Dockerクライアントは、複数のデーモンと通信することが可能です。 Docker registries Dockerレジストリは、Dockerイメージを保存します。Docker Hubは誰もが利用できるパブリックレジストリで、DockerはデフォルトでDocker Hub上のイメージを探すように設定されています。 Docker objects イメージ、コンテナ、ネットワーク、ボリュームなどがあります。 Docker objectsについて具体的に説明します IMAGESとは イメージは、Dockerコンテナを作成するための手順が記載された読み取り専用のテンプレートのことです。多くの場合、イメージは他のイメージをベースにして、さらにカスタマイズされています。例えば、ubuntuのイメージをベースにして、Apache Webサーバーとアプリケーションをインストールし、アプリケーションの実行に必要な設定情報を追加したイメージを作成することができるます。独自のイメージを作成するには、イメージの作成と実行に必要な手順を定義する簡単な構文を持つDockerfileを作成します。 Dockerfileの各命令は、イメージの中にレイヤーを作成します。Dockerfileを変更してイメージを再構築すると、変更されたレイヤーだけが再構築されます。これが、他の仮想化技術と比較して、イメージが軽量、小型、高速である理由の一つです。 コンテナの実行時には、孤立したファイルシステムが使用されます。このカスタムファイルシステムもコンテナイメージによって提供されます。イメージにはコンテナのファイルシステムが含まれているため、アプリケーションの実行に必要なすべてのもの(すべての依存関係、設定、スクリプト、バイナリなど)が含まれていなければなりません。イメージには、環境変数、実行するデフォルトコマンド、その他のメタデータなど、コンテナのその他の設定も含まれています。 CONTAINERSとは コンテナとは、イメージの実行可能なインスタンスのことです。 もう少し具体的に言うと、コンテナとはホストマシン上の他のすべてのプロセスから分離された、あなたのマシン上の別のプロセスのことです。この隔離は、カーネルのnamespaceとcgroupsを利用したもので、Linuxには昔からある機能です。Dockerは、これらの機能を親しみやすく、使いやすくするために努力してきました。 Docker APIやCLIを使って、コンテナの作成、起動、停止、移動、削除を行うことができます。また、コンテナを1つまたは複数のネットワークに接続したり、ストレージを取り付けたり、現在の状態に基づいて新しいイメージを作成したりすることも可能です。デフォルトでは、コンテナは他のコンテナやそのホストマシンから隔離されています。コンテナのネットワーク、ストレージ、その他の基本的なサブシステムを他のコンテナやホストマシンからどの程度隔離するかを制御することができます。 コンテナは、そのイメージと、コンテナの作成時や起動時に指定した設定オプションによって定義され、コンテナが削除されると、永続的なストレージに保存されていない状態の変更はすべて消えます。 コンテナ作成の例 例1 docker run -i -t ubuntu /bin/bash -iは--interactiveのことです。Keep STDIN open even if not attached. つまりインタラクティブモード のこと。-tは、--ttyのことです。Allocate a pseudo-TTY. つまり仮想TTYを割り当てて起動します。 docker run --helpで各種オプションの説明を見ることができます。 このコマンドを打った際に、実際に実行されることは以下の流れです。 ubuntuのイメージがローカルにない場合は、docker pull ubuntuを手動で実行したように、Dockerは設定されたレジストリからイメージを引き出します。 次にdocker container createを手動で実行したように、新しいコンテナが作成されます。 そしてDockerは、その最終層として、コンテナに読み書き可能なファイルシステムを割り当てます。これにより、実行中のコンテナは、そのローカルファイルシステムにファイルやディレクトリを作成したり、変更したりすることができます。 今回はネットワークオプションを指定していないのでDockerは、コンテナをデフォルトネットワークに接続するためのネットワークインターフェースを作成します。これには、コンテナへのIPアドレスの割り当ても含まれます。デフォルトでは、コンテナはホストマシンのネットワーク接続を使って外部ネットワークに接続できます。 Dockerはコンテナを起動し、/bin/bashを実行します。コンテナはインタラクティブに実行され、ターミナルに接続されているため(-iおよび-tフラグによる)、キーボードを使って入力を行い、出力はターミナルに記録されます。 exitと入力して/bin/bashコマンドを終了させると、コンテナは停止します が削除されません。再度起動するか、削除することができます。 例2 docker run -d -p 80:80 docker/getting-started -dはコンテナをdetachedモード(バックグラウンド)で動かすようにしています。 -p 80:80は、ホストのport80番をコンテナのport80番にマッピングしています。 docker/getting-startedは使用するイメージです。 Go言語を使用してコンテナを0から作る様子の講演会は以下のリンクから視聴することができます! またdocker runのリファレンスについては以下に書いています。 Dockerfileの書き方の例 Dockerfileとは、コンテナイメージを作成するためのテキストベースの指示スクリプトです。 こちらをcloneします。cloneできたら、appディレクトリに移動し、Dockerfileという名前でファイルを作成します。そこに以下のように書いてみます。 Dockerfile FROM node:12-alpine RUN apk add --no-cache python g++ make WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"] ターミナルを開いて、Dockerfileのあるappディレクトリに移動します。次に、docker buildコマンドを使ってコンテナイメージを構築します。 docker build -t getting-started . docker run -dp 3000:3000 getting-started //-dpは-dと-pを繋げて書いているものです node:12-alpineイメージのダウンロードが開始されます。 イメージがダウンロードされた後、アプリケーションをコピーし、yarnを使ってアプリケーションの依存関係をインストールします。CMDディレクティブは、このイメージからコンテナを起動する際に実行するデフォルトのコマンドを指定します。 つぐに-tフラグでイメージにタグを付けます。これは単に、最終的なイメージの人間が読める名前と考えてください。イメージにgetting-startedという名前を付けたので、コンテナを実行するときにそのイメージを参照することができます。 docker buildコマンドの最後にある.は、DockerがカレントディレクトリでDockerfileを探すように指示します。 docker runコマンドによって、上記で作成されたgetting-startedイメージを使用してコンテナが起動します。 http://localhost:3000 にアクセスするとアプリケーションを見ることができます。 Dokcerコンテナを操作するその他コマンド //コンテナのidを取得する docker ps //コンテナをストップする docker stop <the-container-id> //ストップ済のコンテナを削除する docker rm <the-container-id> //動いているコンテナをストップして削除する docker rm -f <the-container-id> 現状のサンプルアプリでの問題点 上の例で簡単なtodoアプリを起動したが、現状のままではコードを変更するたびに、コンテナをrestartする必要があります。またコンテナを起動するたびにtodoリストが空に戻ってしまいます。 上記の理由とファイルシステムについて コンテナが実行されると、イメージのさまざまなレイヤーをファイルシステムとして使用します。また、各コンテナには、ファイルの作成、更新、削除を行うための独自の「スクラッチスペース」が用意されています。同じイメージを使用していても、他のコンテナでは変更が反映されません。 各コンテナが起動するたびにイメージ定義からスタートします。コンテナではファイルの作成、更新、削除が可能ですが、コンテナが削除されるとそれらの変更は失われ、すべての変更はそのコンテナに隔離されてしまいます。ボリュームを使えば、このような状況を変えることができます。 Volumeを使用してデータを永続化しよう Volumeは、コンテナの特定のファイルシステムパスをホストマシンに戻す機能を提供します。コンテナ内のディレクトリをマウントすると、そのディレクトリの変更がホストマシンにも反映されます。コンテナの再起動にかかわらず、同じディレクトリをマウントすれば、同じファイルが表示されます。 より詳しい説明はこちら。 Volumeには2種類あります。 named volumeとbind mountです。 named volumeについて 現在使用しているtodoアプリはSQLite Databaseを使用してデータを保存しています。実際にはこちらにのファイルに保存されています。/etc/todos/todo.db named volume(単なるデータのbucketと考えて大丈夫)を使う手順は以下。 ボリュームを作成 docker volume create todo-db データが保存されているディレクトリにアタッチ(マウントと呼ばれる)して、データを永続化する。 docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started -v todo-db:/etc/todosのところでtodo-dbというbucketを/etc/todosにマウントしています。ちなみにdocker volume create todo-dbを省略しても、Dockerは私たちがnamed volumeを使用したいことを認識し、自動的にボリュームを作成してくれます。 コンテナがtodo.dbファイルに書き込むと、ボリューム内のホストにデータが保存されます。 実際にbucketがどこに作成されているのかが気になったら、以下のコマンドを実行すると良いです。 docker volume inspect todo-db //実行結果 Mountpointが実際にデータが格納されている場所です [ { "CreatedAt": "2021-04-11T02:18:36Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/todo-db/_data", "Name": "todo-db", "Options": {}, "Scope": "local" } ] named volumeはデータがどこに保存されているかを気にする必要がないため、単にデータを保存したい場合に最適です。 bind mountについて bind mountでは、ホスト上の正確なマウントポイントを制御します。バインドマウントは、データの永続化にも使用できますが、多くの場合、コンテナに追加データを提供するために使用されます。アプリケーションの開発では、バインドマウントを使ってソースコードをコンテナにマウントすることで、コードの変更をコンテナに反映させ、その変更をすぐに確認できるようにします。 docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ node:12-alpine \ sh -c "yarn install && yarn run dev" -w /appでは、作業ディレクトリ、つまりコマンドが実行される現在のディレクトリを設定します。 -v "$(pwd):/app"では、コンテナ内のホストからカレントディレクトリを/appディレクトリにバインドマウントします。 こうすることでカレントディレクトリのファイルに何か変更を加えても、コンテナを再起動する必要がなく、コンテナ内のファイルにも変更が反映されます。 bind mountを使用することは、ローカル開発のセットアップでは非常に一般的です。そのメリットは、開発マシンにすべてのビルドツールや環境をインストールする必要がないことです。たった1つのdocker runコマンドで、開発環境が引き出され、すぐに使えるようになります。また次に説明するDocker Composeを使用することで、これはコマンドを単純化するのに役立ちます。 Multi container appsで役割ごとにコンテナを分けよう 上記までの説明では1つのコンテナのみでアプリを起動してきました。 しかし1つのコンテナでは解決できない問題があります。例えば以下のような問題です。 APIやフロントエンド、データベースでバージョンを分離したい場合。 ローカルではデータベース用のコンテナを使うが、本番ではデータベース用のマネージドサービスを使いたいと思う場合。 そういった場合、 API用のコンテナ、フロントエンド用のコンテナ、データベース用のコンテナと分けることができます。 例えば先程のtodoアプリでsqliteではなくMySQLを使用する場合を考えてみます。 以下のような図でコンテナ同士が通信する必要があります。 Container networkingについて コンテナは、デフォルトでは分離して実行され、同じマシン上の他のプロセスやコンテナについては何も知らない状態です。このような状態で、あるコンテナが別のコンテナと対話できるようにするには同じネットワークにコンテナを設置する必要があります。 2つのコンテナが同じネットワーク上にあれば、お互いに通信することができます。そうでない場合は通信できません。 ネットワークを作成する。 docker network create todo-app MySQLコンテナを起動し、ネットワークに接続します。コマンドは以下のようになります。 --network todo-appで、todo-appというネットワークに接続されています。-eではデータベースの初期化に使用するいくつかの環境変数を定義しています。 docker run -d \ --network todo-app --network-alias mysql \ -v todo-mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=secret \ -e MYSQL_DATABASE=todos \ mysql:5.7 todoアプリを起動します。 --network todo-appで、todo-appネットワークに接続しています。MYSQL_HOST=mysqlで、先程--network-alias mysqlとして設定したmysql aliasをHOSTとしています。通常は、mysqlは有効なホスト名ではありませんが、Dockerはネットワークエイリアスを持つコンテナのIPアドレスに解決することができます。 docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ --network todo-app \ -e MYSQL_HOST=mysql \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=secret \ -e MYSQL_DB=todos \ node:12-alpine \ sh -c "yarn install && yarn run dev" Docker Composeを使用して楽をしよう Docker Composeは、マルチコンテナ・アプリケーションの定義と共有を支援するために開発されたツールです。Composeでは、YAMLファイルを作成してサービスを定義し、1つのコマンドですべてを起動したり、すべてを停止したりすることができます。 Composeを使うことの大きな利点は、アプリケーション・スタックをファイルで定義し、それをプロジェクト・リポジトリのルートに置いておき(バージョン管理されている)、他の人が簡単にプロジェクトに貢献できることです。 誰かがあなたのレポジトリをクローンしてcomposeアプリを起動するだけでいいのです。 プロジェクトのルートでdocker-compose.ymlというファイルを作成する。 まずファイル内でComposeのファイルフォーマットのversionを宣言する。versionの一覧はこちらです。 version: "3.7". 次にアプリケーションの一部として動作させたいサービス(=コンテナ)のリストを定義します。 services: 例として先程のtodoアプリとMySQLコンテナの定義をdocker composeを使用して行ってみます。 先にですが、完成形は以下のようになります。 docker-compose.yml version: "3.7" services: app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data: appサービスについて servicesの名前をappとしています。サービスの名前ではなんでも好きなものを付けることができます。同時にこれはnetwork aliasになります。 -w /appで指定していた作業ディレクトリはworking_dirで定義することができます。 -v "$(pwd):/app"でbind mountしていたのは、volumesで定義することがができます。docker-composeではカレントディレクトリからの相対パスを使用できます。 mysqlサービスについて docker runのコマンドでは-v todo-mysql-data:/var/lib/mysqlのオプションでnamed volumeが自動的に作成されたが、Composeで実行する場合はそうはいきません。トップレベルのvolume:セクションでボリュームを定義し、サービスコンフィグでマウントポイントを指定する必要があります。 Docker Composeを使用して定義したサービスを起動しよう docker-compose up -dでバックグランドで起動することができます。-dを付けずに起動してログをリアルタイムで見ることもできます。起動すると以下のような表示が出てきます。 createing networkと表示されていますね! デフォルトでは、Docker Composeはアプリケーションスタック専用のネットワークを自動的に作成します(コンポーズファイルで定義していないのはそのためです)。 Creating network "app_default" with the default driver Creating volume "app_todo-mysql-data" with default driver Creating app_app_1 ... done Creating app_mysql_1 ... done 注意ポイント アプリの起動時には、MySQLが起動して準備が整うのを実際に待ってから接続しようとします。Dockerには、他のコンテナを起動する前に、他のコンテナが完全に立ち上がり、実行され、準備が整うのを待つためのビルトインのサポートはありません。 Node ベースのプロジェクトでは、wait-port依存関係を使用することができます。同様のプロジェクトが他の言語/フレームワークにも存在します。 全てのコンテナを終了する すべてを破壊する準備ができたら、docker-compose downを実行するか、Docker Dashboardでアプリ全体のゴミ箱を押すだけです。コンテナは停止し、ネットワークも削除されます。 volumeは削除されません。 volumeも一緒に削除したい場合は、docker-compose down --volumesを実行する必要があります。 ベストプラクティスを学ぼう イメージをbuildしたらdocker scanコマンドを使用してセキュリティ上の脆弱性をスキャンします。 例えばgetting-startedというタグでイメージをビルドした場合は、このようなコマンドを打ちます。docker scan getting-started docker image history getting-startedを使用すると、getting-startedというイメージ内の各レイヤーの作成に使われたコマンドを見ることができます。 ビルド時間短縮のための工夫 前提として、Dockerイメージは、レイヤーが変更されると、下流のレイヤーもすべて再作成する必要があります。 例えば以下のようなDockerfileがあるとします。 Dockerfile FROM node:12-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"] 上記のDockerfileだと、イメージに変更を加えたときにCOPY . .の部分が影響受け、下流のyarnの依存関係を再インストールするところも再び実行されます。つまりイメージに変更を加えるたびに同じ依存関係を使って依存関係を再インストールしています。これを解決するために以下のような最適な形にDockerfileを変更します。 Dockerfile FROM node:12-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "src/index.js"] またDockerfileと同じフォルダに、.dockerignoreというファイルを以下の内容で作成します。 .dockerignore node_modules .dockerignoreファイルは、イメージに関連するファイルだけを選択的にコピーする簡単な方法です。今回のケースでは、2回目のCOPYステップ(COPY ..)でnode_modulesフォルダを省略する必要があります。 そうしないと、RUNステップでコマンドによって作成されたファイルを上書きしてしまう可能性があるからです。 Multi-stage buildsを使用しよう マルチステージビルドは、複数のステージを使ってイメージを作成するための非常に強力なツールです。マルチスタージビルドにはいくつかのメリットがあります。 ビルド時の依存性とランタイムの依存性の分離することができる アプリの動作に必要なものだけを出荷することで全体のイメージサイズを縮小することができる 例えばReactを使用したアプリケーションの例で考えてみます。 Reactアプリケーションを構築する際には、JSコード(通常はJSX)やSASSスタイルシートなどを静的なHTML、JS、CSSにコンパイルするためにNode環境が必要です。サーバーサイドレンダリングを行わないのであれば、本番環境のビルドにNode環境は必要ありません。静的リソースを静的なnginxコンテナに入れて出荷すればいいのです。 すると以下のようにマルチステージビルドを使用してDockerfileを書くことができます。 Dockerfile FROM node:12 AS build WORKDIR /app COPY package* yarn.lock ./ RUN yarn install COPY public ./public COPY src ./src RUN yarn run build FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html この例では、1つのステージ(buildと呼ばれる)で、Nodeを使用して実際にReactのビルドを行います。2番目のステージ(FROM nginx:alpineから始まる)では、buildステージからファイルをコピーしています。最終的なイメージは、最後のステージが作成されている(出力をnginxコンテナにコピーしている)だけです。 以上になります。 次回はLaravel&Reactを使用した環境構築について記事を書いてみようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

APIモックに便利なjson-serverをdockerを使って構築してみる

APIモックをサクッと構築したいなら、ゼロコーディングで30秒でできるという触れ込みのjson-serverがおすすめです。 json-serverはnpmでインストールするのですが、開発マシンを汚したくないときにはdockerを使って構築したいなと思いますよね。ということで、dockerを使ってjson-serverを構築してみました。githubにサンプルコードをのせてあります。 https://github.com/kiyo27/json-server-docker Dockerfileを準備 ベースイメージにnodeを使用してnpmでjson-serverをインストールしています。コンテナ起動時にjson-serverをオプション付きで起動できるようにしているので、コンテナを立ち上げたらそのままjson-serverが利用できます。 FROM node:latest RUN npm install -g json-server WORKDIR /data EXPOSE 3000 ENTRYPOINT ["json-server"] CMD ["--watch", "db.json", "--host", "0.0.0.0"] コンテナ起動 用意したDockerfileを使用してコンテナを起動します。 # ビルド docker build -t json-server . # 起動 docker run --name json-server -p 3000:3000 -v `pwd`/db:/data json-server コンテナが起動できたらhttp://localhost:3000を開いてトップページが表示されたら成功です。 使い方 json-serverはGET, POST, DELETE, PUT, PATCHに対応しています。 GET $ curl -X GET http://localhost:3000/posts [ { "id": 1, "title": "json-server", "author": "typicode" }, { "id": 2, "title": "new post", "author": "user" } ] idを指定して取得もできます。パスパラメータを使用すると、配列ではなくオブジェクトで返却されます。 # クエリパラメータを使用 $ curl -X GET http://localhost:3000/posts?id=1 [ { "id": 1, "title": "json-server", "author": "typicode" } ] # パスパラメータを使用 $ curl -X GET http://localhost:3000/posts/1 { "id": 1, "title": "json-server", "author": "typicode" } _embedを使用すると子要素も指定して取得できます。 $ curl -X GET 'http://localhost:3000/posts?_embed=comments&id=1' [ { "id": 1, "title": "json-server", "author": "typicode", "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ] } ] POST POSTを使用して要素の追加もできます。 $ curl -X POST -H "Content-Type: application/json" -d '{"title":"third post","author":"user"}' http://localhost:3000/posts { "title": "third post", "author": "user", "id": 3 } 追加されたデータはdb.jsonに保存されます。 db.json { "posts": [ { "id": 1, "title": "json-server", "author": "typicode" }, { "id": 2, "title": "new post", "author": "user" }, { "title": "third post", "author": "user", "id": 3 } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } } PUT, PATCH json-serverではデータの更新も可能です。 $ curl -X PUT -H "Content-Type: application/json" -d '{"title":"mod post","author":"user"}' http://localhost:3000/posts/3 { "title": "mod post", "author": "user", "id": 3 } $ curl -X GET http://localhost:3000/posts?id=3 [ { "title": "mod post", "author": "user", "id": 3 } ] $ curl -X PATCH -H "Content-Type: application/json" -d '{"title":"patch post","author"":"user"}' http://localhost:3000/posts/3 { "title": "patch post", "author": "user", "id": 3 } $ curl -X GET http://localhost:3000/posts?id=3 [ { "title": "patch post", "author": "user", "id": 3 } ] DELETE DELETEメソッドを使用すれば要素の削除ができます。 $ curl -X DELETE http://localhost:3000/posts/3 $ curl -X GET http://localhost:3000/posts [ { "id": 1, "title": "json-server", "author": "typicode" }, { "id": 2, "title": "new post", "author": "user" } ] JavaScriptを使用すればいろいろカスタマイズできますが、それはまた今度。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerコマンドをエイリアス設定してすこし楽する

新しい Mac で git コマンドのエイリアス設定を終えたので、dockerコマンド(特にdocker-compose)もついでにやっとこうと思い設定しました。  .bashrcを編集して、bash_profileに反映させます。  .bashrc  と .bash_profile の参考記事 本当に正しい .bashrc と .bash_profile の使ひ分け docker と docker-compose の初歩 .bashrc 作成  ( .bashrcが無い人 ) Mac だとデフォルトで.bashrcが無いようなので作ります。 # ホームに移動 $ cd ~ # bash ~ のファイルを探す $ ls -la | grep 'bash' # 無ければ .bashrc 作成 $ touch .bashrc .bashrc を編集する .bashrc を編集して中身にdocker-composeのエイリアスコマンドを書きます。 # vi エディタ 起動 $ vi ~/.bashrc # エイリアス設定をしますが、設定ははお好みで。 alias dcu='docker-compose up -d' alias dcr='docker-compose restart' alias dpa='docker ps -a' alias dcs='docker-compose stop' # vi エディタ 保存・終了 :wq [補足] ・ イメージ・コンテナの削除系コマンドを設定する人もいると思いますが、僕は外してます。 # 現在のシェルに即時変更を反映させる source ~/.bashrc source ~/.bash_profile dockerが使われているプロジェクトフォルダ直下で試しに dp (docker ps -a) と入力して使えるのを確認! 以上でめでたしめでたし。。だったら良かったんですが、一度ターミナルを閉じてサイド立あげ、先ほどと同様に、 dp -bash: dp: command not found !? どうやら調べていくと、起動時に.bash_profileがbashrcを読み込む設定を追記しないといけない様でした。 というわけで、 # [[注意]] 編集するのは.bashrcではありません $ vi ~/.bash_profile #記載内容 # .bash_profile if [ -f ~/.bashrc ]; then . ~/.bashrc fi [ -f ~/.bashrc ]; の部分で.bashrcファイルの存在を確認しています。 ifと fi の挟まれた部分の~/.bashrc で .bashrc を読み込む様にしています。 (この辺は勉強中なので詳しいかたいらしたらコメントしていただけると嬉しいです!) これで、ターミナルを閉じて立ち上げてもエイリアスコマンドが使える様になりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

fargateコンテナに入りたい時はECSexecを使おう

1. 初めに 初投稿です!未経験からエンジニアに就職を目指しているshotaと申します。 ポートフォリオ作りでインフラの勉強の為、fargateを利用したデプロイをしていたのですが、データのやりとりが中々上手くいきませんでした。 ローカルでは問題ないのに... こういった場合、コンテナの中に入ってローカルとの差分を見るのは一つの選択肢にあるのかなと思います。 ecs(ec2)ならec2インスタンスにSSH or SSMでログインしてdockerコマンドで直接ログインする方法があると思います。 ですが,ecs(fargate)の場合は今までに公式的なログイン方法はありませんでした。 そこで、どうにか方法が無いか調べていると、awsからセッションマネージャーを利用して、SSMエージェント経由でクライアントからコンテナへのアクセスができるという素敵なコンテンツが提供されているのを知りました。 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html クラスメソッドさんもとても分かりやすく紹介していました。 https://dev.classmethod.jp/articles/ecs-exec/ 使用できる条件があるので公式を見てくれたらと思います。 ECSexecは現在マネジメントコンソールの使用はサポートされていません。(4月11日現在) aws-cliも対応しているバージョンを上の記事から対応するものをインストールしていただければと思います。 以降、公式の通りにはなるかと思いますが、簡単な順序を書いていきたいと思います。 この記事はハンズオン形式ではありませんので適宜解釈をしていただければと思います。 2. 方法 初めにiamの権限の付与をします { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" } ] } このiamポリシーをタスクロールにアタッチするのですが、既存のタスクロールがある方はそこに追記する形で問題ないかと思います。(名前は適宜変更した方が分かりやすいと思います) 次に、入りたいコンテナのtaskに先ほどのタスクロールを設定します。 あとは、コマンドライン上で--enable-execute-commandを使えるようにするために足りていないものがあれば公式を参考にダウンロードしてください。 私は既にサービスを立ち上げていたのでupdate-serviceコマンドを使用し、再デプロイしました。 $ aws ecs update-service \ --cluster クラスターの名前 \ --service サービスの名前 \ --enable-execute-command 成功していれば、ターミナル上に "enableExecuteCommand": true, の表示が出ているかと思いますので,grepなりsedなりで探しましょう。 これで、お目当てのコンテナに入ることができます! $ aws ecs execute-command \ --cluster あなたのクラスター \ --task あなたのtaskid \ --container コンテナの名前 \ --interactive \ --command "/bin/sh" コンテナにインストールされているシェルしか使えないので注意しましょう。 3. おわりに これでfargateでもコンテナにログインを簡単にすることができますね! 私でも簡単にできたので、もっとecsexecが広まって欲しいなと思い、この記事を書きました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloudflare WorkersをDockerで(ホストにWranglerをインストールせずに)開発する

Cloudflare Workersで開発するには、通常は公式ドキュメントにあるとおり$ npm install -g @cloudflare/wranglerでCLIツール「wrangler」をPCにインストールして行います。本稿ではwranglerを直接PCにはインストールせずDockerのみで開発してみました。 環境 debian_version 10.9 (ChromeOS Linux) Docker version 19.03.13, build 4484c46d9d docker-compose version 1.27.4, build 40524192 wrangler 1.15.0 設定 下記のようにファイルを設定していきます。 docker-compose.yml version: '3' services: app: build: . volumes: - .:/app ports: - 8080:80 Dockerfile FROM nginx:1.19-alpine WORKDIR /app # nginx COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf # wrangler RUN apk add nodejs npm COPY ./package.json ./ COPY ./package-lock.json ./ RUN npm install --also=dev CMD nginx && npx @cloudflare/wrangler dev package.json { // 中略 "devDependencies": { "@cloudflare/wrangler": "^1.15.0" } } nginx/default.conf server { listen 80; proxy_set_header Host $host:8080; location / { proxy_pass http://localhost:8787; } } nginx:alpineのDockerイメージにwranglerをインストールして両方同時に立ち上げています。こうすることでコンテナ外(ホスト)からwrangler devの実行結果を覗けるようになります。あまりきれいな方法ではないのですが、今回は開発環境のみということで... 「ホスト:8080→nginx:80→wrangler:8787」の順番でポートをつないでいきます。もちろん数字は整合していれば何でも構いません。 $ docker-compose upで立ち上げたら http://localhost:8080 にアクセスすると$ wrangler devの開発サーバの結果を確認することができます。 デプロイは少々面倒ですが、$ docker-compose exec app shでコンテナの中に入った後 # npx @cloudflare/wrangler login # npx @cloudflare/wrangler publish ...することで対応しています。認証情報ファイルをホストに配置してからコピーすることで$ wrangler loginせずに実行できるようにしても良いかも知れません。本格的に開発するようであればCI/CD等のデプロイ環境を組むと思うのであまり気にしなくていいと思います。 この方法で開発したものが以下です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでrustの開発環境を作りたい時のやつ

RUN dnf install -y curl gcc RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH=/root/.cargo/bin:$PATH RUN . ~/.bashrc 用途 Rust開発したい でも、Doker-Hubのコンテナはやだ みたいな時のDockerfileに記載するやつ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【コピペ】Dockerでrustの開発環境を作りたい時のやつ

RUN dnf install -y curl gcc RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH=/root/.cargo/bin:$PATH RUN . ~/.bashrc 用途 Rust開発したい でも、Doker-Hubのコンテナはやだ みたいな時のDockerfileに記載するやつ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6/Docker/MySQL + Elasticsearch 環境構築

はじめに Elasticsearchを触りたいと思ったのだが、Dockerでの環境構築で詰まったので今後のためにメモ。 環境 Rails6・Docker・MySQLによる環境構築 自分の備忘録用に書いたものだが、ここに+elasticsearchを加えていく。 以下のファイル内のmyappは自分が作成したディレクトリ名に置き換える(今回はelasticsearch-railsと命名) Dockerfile FROM ruby:2.7.1 RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list # myappを自分のアプリ名に変更 RUN apt-get update -qq && apt-get install -y nodejs yarn RUN mkdir /elasticsearch-rails WORKDIR /elasticsearch-rails COPY Gemfile /elasticsearch-rails/Gemfile COPY Gemfile.lock /elasticsearch-rails/Gemfile.lock RUN bundle install COPY . /elasticsearch-rails # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"] Gemfile source 'https://rubygems.org' gem 'rails', '6.0.3' Gemfile.lock # 空のままで entrypoint.sh #!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@" docker-compose.yml version: "3" services: # Elasticsearch用のコンテナ elasticsearch: # 下の1行でも環境構築は出来るが、日本語を扱うときに必要なプラグイン(kuromoji)を入れるために、 # elasticsearch用のDockerfileを作成 # image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1 build: context: . dockerfile: Dockerfile-elasticsearch environment: - discovery.type=single-node - cluster.name=docker-cluster - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 ports: - 9200:9200 volumes: - esdata:/usr/share/elasticsearch/data # Kibana用のコンテナ kibana: # elasticsearchとkibanaのimageのバージョン番号を一致 image: docker.elastic.co/kibana/kibana:7.10.1 ports: - 5601:5601 depends_on: - elasticsearch db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password ports: - '3306:3306' command: --default-authentication-plugin=mysql_native_password volumes: - mysql-data:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: # myappを自分のアプリ名に変更 - .:/elasticsearch-rails ports: - "3000:3000" depends_on: - db # elasticsearchのコンテナと関連づける - elasticsearch stdin_open: true tty: true volumes: esdata: mysql-data: elasticsearchとKibanaを追加したので所々変更。 rials用のコンテナ(web)のdepends_onに、elasticsearchのコンテナ名を追加するのを忘れないように Dockerfild-elasticsearch FROM docker.elastic.co/elasticsearch/elasticsearch:7.10.1 # 日本語をあつかうときに使うプラグイン RUN bin/elasticsearch-plugin install analysis-kuromoji # 国際的に規約されてる文字の解析器 RUN bin/elasticsearch-plugin install analysis-icu アプリ作成 --database=mysqlを忘れると、 config/database.ymlのadapterがmysql2ではなくsqliteになってしまったので注意 --force:「強制的に」と言う意味 --no-deps:リンクされたコンテナを起動しない --skip-test:minitestの作成を防ぐ。 --api:APIモードでRailsプロジェクトを作成し、APIには不要なView・UI関連のライブラリがインストールされない。 --webpacker:webpacker をインストール docker-compose run web rails new . --force --no-deps --database=mysql --webpacker 私の場合、ここで下のエラーが発生 response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"rails\": executable file not found in $PATH": unknown ここでbuildしたら治るとのことだったので実行。 docker-compose build 詳しいことは分かっていないが解決したので、仕切り直して先に進める docker-compose run web rails new . --force --no-deps --database=mysql --webpacker docker-compose build config/databas.yml変更 config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= ENV.fetch("MYSQL_USERNAME", "root") %> password: <%= ENV.fetch("MYSQL_PASSWORD", "password") %> host: <%= ENV.fetch("MYSQL_HOST", "db") %> development: <<: *default database: elasticsearch_rails_development test: <<: *default database: elasticsearch_rails_test production: <<: *default database: elasticsearch_rails_production username: elasticsearch_rails password: <%= ENV['ELASTICSEARCH_RAILS_DATABASE_PASSWORD'] %> DBを作成する docker-compose run --rm web bundle exec rails db:create 起動し、動作確認する docker-compose build docker-compose up Rails確認 http://localhost:3000 にアクセスして、お馴染みの画面が出ればOK Kibana確認 http://localhost:5601 にアクセスし、ページが表示されればOK Elasticsearch確認 Curlコマンドでリクエストを投げ、下記のようなクラスタやバージョン情報が含まれるレスポンス返ってくればOK $ curl -XGET http://localhost:9200/ { "name" : "7d712c1f3298", "cluster_name" : "docker-cluster", "cluster_uuid" : "fA4Th3p8RNqMzyJxUlwrYw", "version" : { "number" : "7.10.1", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa", "build_date" : "2020-12-05T01:00:33.671820Z", "build_snapshot" : false, "lucene_version" : "8.7.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" } 参考記事 DockerでRails,Postgres,ElasticSearchの開発環境を構築する方法 docker環境でのRailsアプリの立ち上げ RailsとElasticsearchで検索機能をつくり色々試してみる - その1:サンプルアプリケーションの作成 おわりに 毎度毎度環境構築で詰まりますね(ーー;)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker環境構築[Django+Nginx+MySQL]

構成 root ├── docker-compose.yml ├── mysql ├── sql ├── nginx │ ├── conf │ │ └── app_nginx.conf │ └── uwsgi_params └── python ├── Dockerfile └── requirements.txt Django Dockerfile FROM python:3.9 #バッファが溜まってから出力するのを避ける ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY requirements.txt /code/ RUN pip install --upgrade pip && pip install -r requirements.txt COPY . /code/ requirements.txt Django~=3.2 uwsgi PyMySQL django-environ uWSGIの設定 uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name; Nginxの設定 app_nginx.conf upstream django { ip_hash; server python:8001; } server { listen 8000; server_name 127.0.0.1; charset utf-8; location /static { alias /static; } location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; } } server_tokens off; docker-composeの設定 docker-compose.yml version: '3' services: nginx: image: nginx:1.13 ports: - "8000:8000" volumes: - ./nginx/conf:/etc/nginx/conf.d - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params - ./static:/static depends_on: - python db: image: mysql:5.7 command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: todoList MYSQL_USER: user MYSQL_PASSWORD: password TZ: 'Asia/Tokyo' volumes: - ./mysql:/var/lib/mysql - ./sql:/docker-entrypoint-initdb.d python: build: ./python command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/mylog.log volumes: - ./src:/code - ./static:/static expose: - "8001" depends_on: - db MySQLの設定 sql/init.sql GRANT ALL PRIVILEGES ON test_todoList.* TO 'user'@'%'; FLUSH PRIVILEGES; プロジェクトの作成 terminal % docker-compose run python django-admin.py startproject app . DB設定 settings.py import os import pymysql # connect mysql pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'todoList', 'USER': 'user', 'PASSWORD': 'password', 'HOST': 'db', 'PORT': '3306', } } Migration terminal % docker-compose run python ./manage.py makemigrations % docker-compose run python ./manage.py migrate terminal % docker-compose up -d CSS適用 settings.py STATIC_URL = '/static/' STATIC_ROOT = '/static' terminal % docker-compose run python ./manage.py collectstatic *注意 git管理する際は、MySQLの中身をオープンにするのはセキュリティ的によろしくないので.gitignoreに下記を追加しておきましょう。 mysql/* 参照
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む