初心者でもDockerでAmazonLinux+Go(Echo)+Mysqlの環境構築しつつ簡単なAPIを作って動かす


DockerでAmazonLinux+Go+Mysqlの環境構築する

PHPerだったけど今度はGoやっていくので環境をDockerで作ってそこで簡単なAPIをGoのフレームワーク「Echo」で作っていく

環境

ちなみに作業環境はWindows10 Proのi7メモリ32GBノートPCです

ディレクトリ構成

|-Dockerfile
|-docker-compose.yml
|-./src
    |-main.go

Dockerfile

まずAmazonLinuxにGoをインストールしたイメージを作成する

FROM amazonlinux:latest

ENV GOPATH /go
ENV PATH /usr/local/go/bin:/go/bin:$PATH

WORKDIR /usr/src

# go install
RUN yum update -y \
    && yum install -y tar \
    && yum install -y gzip \
    && curl -OL https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz \
    && tar -C /usr/local -xzf ./go1.13.3.linux-amd64.tar.gz \

# git install for go get command
RUN yum install -y git

# go library
RUN  go get github.com/go-sql-driver/mysql \
        && go get github.com/labstack/echo

CMD ["go", "run", "main.go"]

イメージ生成(docker build -t )

イメージ名は何でもいいですけどここではtest-aws_go-imgとします(.は同ディレクトリを指す)

docker build -t test-aws_go-img .

docker-compose.yml

上記でビルドして作成したイメージ(test-aws_go-img)をdocker-compose.ymlで指定

docker-compose.yml
version: '3.7'
services:
  test-aws_go-img:
    build: .
    container_name: test_app # わかりやすいコンテナ名にしておく(任意)
    ports:
      - 8080:8080
  db:
    container_name: test_db # わかりやすいコンテナ名にしておく(任意)
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password # 従来の認証方式にしておく
    volumes:
      - db-store:/var/lib/mysql
      - ./logs:/var/log/mysql
    environment:
      - MYSQL_DATABASE=test_todo
      - MYSQL_ROOT_PASSWORD=password
      - TZ=Asia/Tokyo
    ports:
      - 3307:3306
volumes: # データの永続化
  db-store:

これでDocker周りは完了

main.go

アクセスするとテーブルに登録されているデータをJSONで返すようなかんたんなAPIを作る

main.go
package main

import (
    "database/sql"
    "fmt"
    "net/http"

    _ "github.com/go-sql-driver/mysql"
    "github.com/labstack/echo"
)

// JSON用の構造体を定義
type Task struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func main() {
    e := echo.New()
    e.GET("/tasks", getTasks)

    e.Start(":8080")
}

func dbConnect() *sql.DB {
    // DB接続処理
    db, err := sql.Open("mysql", "root:password@tcp(test_db)/test_todo")
    if err != nil {
        panic(err.Error())
    }
    return db
}

func getRows(db *sql.DB) *sql.Rows {
    rows, err := db.Query("SELECT id,name FROM tasks")
    if err != nil {
        panic(err.Error())
    }
    return rows
}

func getTasks(c echo.Context) error {
    // DB接続
    db := dbConnect()
    defer db.Close()
    rows := getRows(db)
    defer rows.Close()

    task := Task{}
    var results []Task
    for rows.Next() {
        err := rows.Scan(&task.ID, &task.Name)
        if err != nil {
            panic(err.Error())
        } else {
            results = append(results, task)
        }
    }

    return c.JSON(http.StatusOK, results)
}

Docker起動

動くか確認するためにバックグラウンドのオプションはつけないで普通に起動

docker-compose up

無事起動したら次に確認用のサンプルデータを入れていく

DBへ接続してデータを入れる

別の画面を開いて(Windowsならコマンドプロンプトとか)MySQLのコンテナの中に入る

docker exec -it test_db bash

MySQLへログイン(パスワードは上記で設定したpassword

# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.18 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test_todo;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

以下のSQLを流す(コピペで可)

SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

SET NAMES utf8mb4;

CREATE DATABASE `test_todo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `test_todo`;

DROP TABLE IF EXISTS `tasks`;
CREATE TABLE `tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO `tasks` (`id`, `name`) VALUES
(1,"go"),
(2, "php"),
(3, "java"),
(4, "html"),
(5, "css");

念の為入ったか確認しておく

mysql> select * from tasks;

URLを叩いてJSONが帰ってくるか確認

準備ができたのでターミナルやらでcurlコマンドを叩く

curl -s http://localhost:8080/tasks

すると以下のようにJSONでデータが取得出来る

[{"id":1,"name":"go"},{"id":2,"name":"php"},{"id":3,"name":"java"},{"id":4,"name":"html"},{"id":5,"name":"css"}]

以下GitBashから実行した様子

以下はChromeからアクセスした際の様子

おわり

  • 80%くらいの確率で動くと思うんですが動かなかったらおしえてほしいです
  • それ以外でもこうしたほうがいい等あればコメント下さい

参考URL

などなど