Docker は、アプリケーションのパッケージ化、配布、展開を簡素化するコンテナ化プラットフォームです。 Go と Docker の利点を活用して、アプリケーションの効率、移植性、セキュリティを強化できます。
このチュートリアルは、Docker を使用して Go アプリケーションを構築およびデプロイする方法を説明することに重点を置いています。コンテナ化してデプロイする、Gorilla Mux および GORM パッケージを使用して RESTful API を構築することで学習します。
Docker を使用して Go アプリを構築してコンテナ化するには、Go と Docker をコンピューターにインストールする必要があります。
システムに Go と Docker がインストールされていることを確認してください。 Go は公式 Go ダウンロード Web サイトからダウンロードでき、Docker は Docker Hub からダウンロードできます。まだウェブページにアクセスしていない場合は、ウェブページにアクセスし、特定のオペレーティング システムのインストール手順に従ってください。
この記事では、Docker を使用して Go アプリをデプロイする方法を説明し、Go アプリケーションのコンテナ化を含む、Docker と Postgres データベースのインストールと設定について詳しく説明します。
インストール後、必要に応じて環境変数とパスを設定して Go 開発環境を構成します。必要なディレクトリ構造を備えた作業用の Go ワークスペースがあることを確認してください。
さらに、Docker のコマンドライン インターフェイス (CLI) と Docker の基本的な概念を理解することができます。
このプロジェクト用に新しいディレクトリを作成し、 go mod init コマンドを実行してディレクトリを Go プロジェクトとして初期化します。
go mod init
Go プロジェクトを初期化した後、次のコマンドを実行して、GORM および Gorilla Mux パッケージを依存関係としてプロジェクトに追加します。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
ルーティングには Gorilla Mux パッケージを使用します。 GORM パッケージは、インストールしたドライバー パッケージ (この場合は Postgres) とともに、SQL データベース操作に Go タイプを使用するためのインターフェイスを提供します。
このチュートリアルでは、一般的な Go レイヤード アーキテクチャ スタイルを使用し、インターフェイスを使用してアプリのさまざまなコンポーネントと対話します。
アプリケーションのディレクトリ構造は次のとおりです。
go mod init
このプロジェクト構造はよく整理されており、さまざまなコンポーネント間の懸念事項が明確に分離されているように見えます。この組織により、Go API の成長に合わせた維持と拡張が容易になります。
これは Go の標準ではありません。ただし、多くの Go 開発者とオープンソース プロジェクトは、アプリケーションにこの構造を使用しています。
アプリケーションのデータベース機能をセットアップします。構造体を使用してモデルを定義し、データベースに接続し、データベースでの挿入操作の移行をセットアップする必要があります。
データベースの実装に必要なインポートのリストは次のとおりです。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
最初のタスクは、アプリのデータベース スキーマに一致する Strut を定義することです。 GORM は、フィールドに追加のオプションと制約を指定するためのタグを提供します。
. ├── Dockerfile ├── cmd │ └── server │ └── main.go └── internal ├── http │ ├── handlers.go │ └── users.go ├── models │ ├── database.go │ ├── migrations.go │ └── users.go └── users └── user.go 6 directories, 11 files
User 構造体は、データベース内のユーザー データを操作するためのモデルを表します。
database.go ファイルで、データベース接続インスタンスをカプセル化する構造体を宣言します。この構造体を使用して、データベース実装パッケージの他の部分からデータベースに接続します。
go mod init
次に、データベース実装とデータベース プログラムをデータベースに接続するデータベース接続関数を作成します。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
NewDatabase 関数は、新しいデータベース インスタンスを作成し、データベースへの接続を確立します。これはデータベース インスタンスへのポインタを返します。エラーがあれば、プロセス中にエラーが発生します。
データベース接続が成功したら、次のように関数を使用してデータベース実装の移行機能をセットアップできます。
. ├── Dockerfile ├── cmd │ └── server │ └── main.go └── internal ├── http │ ├── handlers.go │ └── users.go ├── models │ ├── database.go │ ├── migrations.go │ └── users.go └── users └── user.go 6 directories, 11 files
MgrateDB 関数は、データベース クライアントの AutoMigrate 関数を使用して User 構造体の自動移行を設定し、プロセス中にエラーが発生した場合はエラーを返します。
データベース スキーマの構造体を定義した users.go ファイルで、データベース実装の関数の定義に進むことができます。
ここでは、データベースに対する CRUD 操作を担当する CreateUser、GetUserByID、UpdateUser、および DeleteUser 関数を示します。
package models import ( // imports from the user implementation "BetterApp/internal/users" "context" "gorm.io/gorm" "fmt" "gorm.io/driver/postgres" "gorm.io/gorm/schema" "os" )
ユーザー実装はこれらの関数を呼び出してデータベース機能にアクセスします。
ユーザー実装は、データベースから HTTP 実装にデータを中継する際に重要な役割を果たします。
データベース実装の構造体と一致する構造体を定義し、使用するフィールドに JSON タグを追加します。次に、HTTP 実装からのデータを使用してデータベース関数を呼び出す関数を定義します。
ユーザー実装に必要なインポートは次のとおりです:
// internal/models/users.go type User struct { gorm.Model Username string `gorm:"unique;not null"` Email string `gorm:"unique;not null"` IsActive bool `gorm:"not null"` }
JSON タグを含む構造は次のとおりです。 gorm.Model フィールドの json:"-" は、JSON 操作からフィールドを除外することを指定します。
// internal/models/database.go type Database struct { Client *gorm.DB }
次に、ユーザー実装関数のメソッドを含むインターフェイス、ユーザー実装のサービス構造体、サービス実装を初期化する関数を宣言します。
// internal/models/database.go func NewDatabase() (*Database, error) { // Construct a connection string using environment variables for database configuration. configurations := fmt.Sprintf("host=%v port=%v user=%v password=%v dbname=%v sslmode=%v", os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_USERNAME"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("SSL_MODE")) // Open a connection to the database using GORM and PostgreSQL driver. db, err := gorm.Open(postgres.New(postgres.Config{ DSN: configurations, PreferSimpleProtocol: true, }), &gorm.Config{NamingStrategy: schema.NamingStrategy{ SingularTable: true, }}) if err != nil { return nil, err } // Enable connection pooling by configuring maximum idle and open connections. sqlDB, err := db.DB() if err != nil { return nil, err } sqlDB.SetMaxIdleConns(10) sqlDB.SetMaxOpenConns(100) // Return the Database instance with the established database connection. return &Database{ Client: db, }, nil }
インターフェイスとサービスは、ユーザー実装の外部でユーザー関連の操作を管理するのに役立ちます。
次に、データベース実装を呼び出す UserService 構造体実装のメソッドを定義できます。
// internal/models/migrations.go func (d *Database) MigrateDB() error { log.Println("Database Migration in Process...") // Use GORM AutoMigrate to migrate all the database schemas. err := d.Client.AutoMigrate(&User{}) if err != nil { return err } log.Println("Database Migration Complete!") return nil }
CreateUser、GetUserByID、UpdateUser、および DeleteUser 関数は、データベース実装で CRUD 操作を呼び出す役割を果たします。 HTTP 実装はこれらの関数を呼び出してデータベースにアクセスします。
HTTP 実装は、受信リクエストを受信して対話するアプリケーションの一部です。
HTTP 実装全体で必要なインポートのリストは次のとおりです:
go mod init
まず、構造体を宣言し、Router インスタンス、HTTP インスタンス、およびユーザー サービスのインスタンスを含めます。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
次に、Handler 構造体へのポインターを返す関数を作成します。ここでサーバーとハンドラーを構成できます。
. ├── Dockerfile ├── cmd │ └── server │ └── main.go └── internal ├── http │ ├── handlers.go │ └── users.go ├── models │ ├── database.go │ ├── migrations.go │ └── users.go └── users └── user.go 6 directories, 11 files
NewHandler 関数は、HTTP リクエスト ハンドラーをセットアップして構成し、サーバー設定とルートも定義しながら、特定のサービスに対する受信 HTTP リクエストを処理できるようにします。
NewHandler 関数で呼び出した mapRoutes 関数は、ルートをそれぞれのハンドラー関数にマッピングすることでルートを設定します。
package models import ( // imports from the user implementation "BetterApp/internal/users" "context" "gorm.io/gorm" "fmt" "gorm.io/driver/postgres" "gorm.io/gorm/schema" "os" )
次に、ハンドラー関数とその機能を定義します。 ここでは、HTTP リクエストをインターセプトし、操作に基づいて応答する役割を担う CreateUser、GetUserByID、UpdateUser、および DeleteUser 関数を示します。
// internal/models/users.go type User struct { gorm.Model Username string `gorm:"unique;not null"` Email string `gorm:"unique;not null"` IsActive bool `gorm:"not null"` }
これで、サーバーを起動するための機能を作成できます。
// internal/models/database.go type Database struct { Client *gorm.DB }
Serve 関数は、指定されたポートでサーバーを起動し、プロセス中にエラーが発生した場合はエラーを返します。
main.go ファイルに実装をインポートして実装を結合し、アプリを実行します。
// internal/models/database.go func NewDatabase() (*Database, error) { // Construct a connection string using environment variables for database configuration. configurations := fmt.Sprintf("host=%v port=%v user=%v password=%v dbname=%v sslmode=%v", os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_USERNAME"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("SSL_MODE")) // Open a connection to the database using GORM and PostgreSQL driver. db, err := gorm.Open(postgres.New(postgres.Config{ DSN: configurations, PreferSimpleProtocol: true, }), &gorm.Config{NamingStrategy: schema.NamingStrategy{ SingularTable: true, }}) if err != nil { return nil, err } // Enable connection pooling by configuring maximum idle and open connections. sqlDB, err := db.DB() if err != nil { return nil, err } sqlDB.SetMaxIdleConns(10) sqlDB.SetMaxOpenConns(100) // Return the Database instance with the established database connection. return &Database{ Client: db, }, nil }
アプリの起動をインスタンス化する Run 関数を main.go ファイルで宣言し、main 関数でその関数を呼び出すことができます。
// internal/models/migrations.go func (d *Database) MigrateDB() error { log.Println("Database Migration in Process...") // Use GORM AutoMigrate to migrate all the database schemas. err := d.Client.AutoMigrate(&User{}) if err != nil { return err } log.Println("Database Migration Complete!") return nil }
Run 関数は、データベース インスタンスを作成し、移行機能を初期化し、HTTP およびユーザー実装を初期化し、サーバーを起動します。
main 関数で Run 関数を呼び出して、アプリケーションを起動できます。
// internal/models/users.go func (d *Database) CreateUser(ctx context.Context, user *users.User) error { newUser := &User{ Username: user.Username, Email: user.Email, IsActive: false, } if err := d.Client.WithContext(ctx).Create(newUser).Error; err != nil { return err } return nil } // GetUserByID returns the user with a specified id func (d *Database) GetUserByID(ctx context.Context, id int64) (users.User, error) { user := users.User{} if err := d.Client.WithContext(ctx).Where("id = ?", id).First(&user).Error; err != nil { return users.User(User{}), err } return users.User(User{ Username: user.Username, Email: user.Email, IsActive: user.IsActive, }), nil } // UpdateUser updates an existing user in the database func (d *Database) UpdateUser(ctx context.Context, updatedUser users.User, id uint) error { // Check if the user with the specified ID exists var existingUser User if err := d.Client.WithContext(ctx).Where("id = ?", id).First(&existingUser).Error; err != nil { return err } // Update the fields of the existing user with the new values existingUser.Username = updatedUser.Username existingUser.Email = updatedUser.Email existingUser.IsActive = updatedUser.IsActive // Save the updated user back to the database if err := d.Client.WithContext(ctx).Save(&existingUser).Error; err != nil { return err } return nil } // DeleteUser deletes a user from the database by their ID func (d *Database) DeleteUser(ctx context.Context, id uint) error { // Check if the user with the specified ID exists var existingUser User if err := d.Client.WithContext(ctx).Where("id = ?", id).First(&existingUser).Error; err != nil { return err } // Delete the user from the database if err := d.Client.WithContext(ctx).Delete(&existingUser).Error; err != nil { return err } return nil }
Docker を使用してコンテナ化することを検討する前に、アプリケーションは正常に実行される必要があります。
プログラムの構築と実行が正常に完了したので、Docker を使用したコンテナ化に進むことができます。
Dockerfile にはビルドと最終ステージの 2 つのステージがあります。このアプローチにより、イメージ サイズが削減され、攻撃対象領域が減少することでセキュリティ リスクが最小限に抑えられ、効率的なランタイム パフォーマンスが保証され、さまざまな開発および展開段階での再現性が促進されます。
また、Alpine Linux を Docker イメージのベース イメージとして使用します。これは、Alpine Linux がミニマリスト設計によりより効率的かつ安全になり、イメージ サイズが小さくなり、ビルドが高速になり、攻撃対象領域が減少するためです。
Dockerfile でビルドと最終ステージを使用すると、Docker イメージを効率的に作成できます。ビルド ステージは、ビルド ツールと依存関係を含むベース イメージから始まり、アプリケーション アーティファクトをコンパイルして、潜在的に大規模な中間イメージを生成します。
ビルドステージの Dockerfile の内容は次のとおりです:
go mod init
最終段階では、より小さい基本イメージを使用し、必要なランタイム コンポーネントのみをコピーして、実稼働用に最適化されたコンパクトなイメージを作成します。
最終段階の Dockerfile の内容は次のとおりです。
go mod init
Dockerfile を作成した後、ファイルのビルドと実行に進むことができます。
このコマンドを実行して、ビルド コマンドでファイルから Docker イメージをビルドします。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
-t フラグは、Docker イメージのタグを betterapp として指定し、次のドット (.) は、現在のディレクトリに Dockerfile を構築することを指定します。
run コマンドを使用してイメージを実行し、-p フラグを使用してコンテナからホスト マシンへのポート マッピングを指定できます。
. ├── Dockerfile ├── cmd │ └── server │ └── main.go └── internal ├── http │ ├── handlers.go │ └── users.go ├── models │ ├── database.go │ ├── migrations.go │ └── users.go └── users └── user.go 6 directories, 11 files
後続の -e フラグは、アプリケーション用の環境変数を指定するためのものです。
Docker Compose は、複数の Docker コンテナの操作を簡素化するコンテナ オーケストレーション ツールです。 Docker compose を使用して、Go アプリとそのコンポーネントをオーケストレートできます。
YAML ファイルを使用して命令を指定すると、Docker Compose がアプリケーションをセットアップして、時間と複雑さを節約します。
まず、以下のコマンドを使用して Docker Compose YAML ファイルを作成し、エディターでファイルを開きます。
package models import ( // imports from the user implementation "BetterApp/internal/users" "context" "gorm.io/gorm" "fmt" "gorm.io/driver/postgres" "gorm.io/gorm/schema" "os" )
Dockerfile を作成したら、アプリをデプロイするためのコマンドとディレクティブの作成を開始できます。
// internal/models/users.go type User struct { gorm.Model Username string `gorm:"unique;not null"` Email string `gorm:"unique;not null"` IsActive bool `gorm:"not null"` }
YAML ファイルは、データベース コンテナ インスタンスである my-postgres と、環境変数、ポート、依存関係を構成する前の Go アプリケーションである Web サービスの 2 つのサービスを定義します。
これで、docker-compose build コマンドを使用してイメージのビルドに進むことができます。
// internal/models/database.go type Database struct { Client *gorm.DB }
出力は次のようになります:
最後に、docker-compose up コマンドを使用してコンテナを実行できます。
go mod init
-d フラグは、ターミナルセッションに依存しないデタッチモードでコンテナを実行します。
コマンドの実行結果は次のとおりです:
ターミナルを閉じても、コンテナーは実行を続行する必要があります。
コンテナが起動したら、CURL リクエストを実行して API をテストできます。
go get github.com/gorilla/mux go get gorm.io/gorm go get gorm.io/driver/postgres
おめでとうございます。Docker と Docker Compose を使用して正常に動作する Go アプリをデプロイして実行できました。
Docker と Docker Compose を使用して Go アプリのデプロイメントを構築および簡素化する方法を学びました。開発の旅を続けるにつれて、ここで得たスキルと理解は、スムーズな導入と優れた運用を確保する上で不可欠な資産となることがわかります。
Dockerfile ビルドの最適化や、大規模なアプリケーション向けの Docker Swarm の実装など、高度な Docker 機能を検討することを検討してください。
以上がDocker を使用して Go アプリケーションをデプロイする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。