データベースにローカルで接続された API の開発とテストは冗談ではありません。データベースが問題となることがよくあります。ただし、Docker を使用すると、プロセスがより簡単かつシンプルになり、レプリケーションが容易になります。このブログでは、MySQL データベースを使用して Golang API を Docker 化し、Docker Compose に対応できるようにする方法を説明します
デモ用に、この RESTful Golang API を作成しました。 MySQL データベースに対する スケジュール の作成、削除、編集などの CRUD 操作を実行できます。エンドポイント、メソッドなどの詳細については、プロジェクトの README を参照してください。私たちの主な目標は Dockerization の部分に焦点を当てることであるため、API がどのように機能するかについてはあまり深くは説明しません。
アプリを Dockerzing するには、Dockerfile を作成する必要があります。 Dockerfile の書き方には何百もの方法があり、間違っていることも正しいこともありません。すべての個人/企業には独自の一連のプラクティスと書き方があることをお伝えしておきます。私たちのケースでは、Dockerfile の 4 つのベスト プラクティスに従って、より小さく、より安全な、より適切で最適化されたイメージを取得します。 Dockerfile の作成に入る前に、4 つのプラクティスすべてと、それらを実装する理由を理解しましょう。
軽量の基本イメージの使用: ほぼすべての言語に、イメージの軽量バージョンがあります。軽いというのは、数メガバイト小さいという意味ではなく、10 分の 1 まで小さくすることもできます。軽い理由は、不要な依存関係が含まれていないため、サイズが小さくなり、安全性が高まるからです。はい、依存関係が増えるとセキュリティ リスクも高まります。ノード、Golang などのブルズアイ バージョンとアルパイン バージョンが用意される予定です。
マルチステージ ビルド: これらは Docker の優れた機能の 1 つであり、ビルド ステップを並行して実行できるほか、必要なファイルなどをコピーして最終イメージを作成することもできます。他のステップから削除され、プログラムの実行に必要な項目のみが含まれています。
バイナリの作成: 多くの言語はソース コードからのバイナリの作成をサポートしており、完全なソース コードを処理する必要がないため、バイナリのサイズが小さくなり、実行がはるかに簡単になります。また、言語の壁に関係なく、どんな環境でも実行できます。
レイヤーの分割: ご存知のとおり、Dockerfile 内のすべての命令はレイヤーであり、レイヤーを分割することはビルドを高速化する良い方法です。たとえば、ソースからすべてのファイル (インストールする依存関係ファイルとともに) をコピーして依存関係をインストールする場合、依存関係に変更を加えなかったとしても、イメージを再構築するたびに、すべてのファイルをコピーし、依存関係をインストールします。これを克服するために、それらをいくつかのレイヤーに分割し、依存関係ファイルを 1 ステップでコピーしてインストールできるようにします。次のステップでは、すべてのファイルをコピーします。コードに変更を加えて再構築すると、今度はすべてのファイルをコピーしているレイヤーのみが再構築され、依存関係のステップは残ります (変更がないためキャッシュされます)。以下の Dockerfile にも例があります。基本イメージ、依存関係など、変更が少ないものは上から下のアプローチになるように Dockerfile を作成します。
それでは、Go API 用に作成した Dockerfile を次に示します。
# Build Stage FROM golang:alpine3.20 AS builder WORKDIR /build COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o /app . # Final Stage FROM alpine:3.20 COPY --from=builder /app /app CMD ["/app"]
FROM では、本格的な golang を使用してステップ ビルダーに名前を付ける代わりに、golang:alpine バージョンをベース イメージとして使用したことがわかります。名前/ラベルは、ファイルを 1 つのステージから別のステージにコピーする際に役立ちます。別の。その後、作業ディレクトリを作成しました。次に、すべてのファイルを一緒にコピーする代わりに、go.mod と go.sum をコピーして依存関係をインストールしました (その理由は、上記の レイヤーの分割 のポイントで説明しました)。
依存関係がインストールされたら、残りのファイルをコピーします。次に、 go build を実行してソース コードからバイナリを作成し、 -o 出力フラグを使用して現在の場所にバイナリに名前を付けます。
さて、ここで話が面白くなります。最終段階では、golang イメージなどは必要ありません。バイナリができたので、Alpine ベース イメージを使用できます。また、プログラミングに関係なく、どの Linux システムでも実行できます。言語の詳細。次のステップでは、バイナリをビルダー ステップから最終ステージにコピーし、バイナリを実行できます。
それだけです。これがアプリの Dockerzie の方法であり、ユーザーの作成や非 root として実行するなどのベスト プラクティスを導入することで Dockerfile をさらに改善できます。これで、Dockerfile を使用してイメージを構築して実行し、リモートまたはリモートに接続できるようになります。ローカル MySQL サーバーに必要な認証情報を提供して、それらの API エンドポイントにアクセスします。
But, we will not stop here we will take a step further, and we will also run a MySQL server in a container and connect with our app. But, one point to note here is we can run a spin of a MySQL container and connect our API container to that, but there is so much manual work and long commands to type in the terminal, and things can go wrong. To overcome this we will use Docker Compose instead to make our life easier.
Let's create a file called compose.yml and use the blow config.
services: app: container_name: go-api build: context: . dockerfile: Dockerfile image: go-api ports: - 8080:8080 environment: - DB_HOST=mysql - DB_PORT=3306 - DB_USER=user - DB_PASSWORD=password - DB_NAME=my-database depends_on: mysql: condition: service_healthy networks: - go-network mysql: container_name: go-mysql image: mysql:9.0 environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=user - MYSQL_PASSWORD=password volumes: - dbdata:/var/lib/mysql networks: - go-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 3 volumes: dbdata: networks: go-network: driver: bridge
It's a pretty basic configuration, but a couple of key things I want to mention is that if we see DB_HOST is mysql, there is no localhost or ip because in compose services communicate with other services by the service name. This is out-of-the-box networking provided by Docker Compose.
Another point, it often happens when working with Docker Compose where we have two services: an app and a database, and the app service starts first and crashes because the database isn't ready when the app tries to connect. To overcome this, we set up a healthcheck for the database to confirm its readiness. Then, in our app service, we can use depends_on with a condition to ensure the app only starts when the database service is healthy.
Now when we do Docker compose for 1st time, we might encounter an error saying permission denied because it doesn't have permission as well as a database with the name my_database, so we need to both by execing into the container.
Even though our app has crashed the DB is still up and running. We can check by doing docker ps.
Now exec into the container by doing docker exec -it
mysql -u root -p
It will ask for the password, enter the password you mentioned in the compose.yml file. Once we log in, we can create a database. Create a database with the same name specified in the compose file. In my case, it's my_database. Execute the below command:
CREATE DATABASE my_database;
Now to give the right privileges and flush it execute the below command.
GRANT ALL PRIVILEGES ON my_database.* TO 'user'@'%'; FLUSH PRIVILEGES;
Once we are done, we need to stop the running compose service and restart again by doing docker compose up
That's it for this blog. I'm glad you're still reading and made it to the end—thank you so much for your support and reading. I sometimes share tips on Golang on Twitter. You can connect with me there.
以上がMySQL を使用した Golang API の Docker 化と Docker Compose サポートの追加の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。