Help us understand the problem. What is going on with this article?

Golang x Beego x Docker x CircleCI x npmで開発環境をサクッと作ってみよう

DockerとCircleCIなどを組み込みつつGolangのBeego開発環境を構築します。
本稿では以下を前提とします。

前提となる知識
・terminalのコマンド操作
・viまたはエディタの操作
・Docker,docker-composeの知識
・gitやgithubの基本的な操作

前提となる条件
・OSはmacOSを前提とします。どうしてもWindowsなどの場合はVagrantでLinuxの仮想環境を立てるなどして自力で対応してみてください。
・バージョン管理のツールはGithubを用います。

この記事で書いていること
・Beegoの0からの環境構築
・Dockerとdocker-composeでコンテナ環境構築
・CircleCIの0からの設定
・フロントエンド環境の0からの構築

この記事に書いてないこと
・Go言語特有の実装方法やtipsなど

Beego環境のセットアップ

Goのインストールの確認

以下のコマンドでGoがローカルに入っているか確認しましょう。

go version

not foundと表示される場合は公式サイトからパッケージのダウンロードをするかbrewでインストールしましょう。
インストール後はGOPATHの設定が必要です。
手順としては大体以下ですが、環境によって異なることがあるので公式を確認しましょう。

  • GOPATHとなるディレクトリを作成しておく
mkdir ~/go/
  • ~/.bash_profileを開く
vim ~/.bash_profile
  • 以下を追記する
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
  • 保存後に反映
source ~/.bash_profile

Beegoのインストール

Goのインストールが完了してgoコマンドが使えるようになったことを確認できたらBeegoをインストールしましょう。
公式サイトを参考に必要なツールをインストールする。

go get -u github.com/astaxie/beego
go get -u github.com/beego/bee

正しく実行されると $GOPATH/bin の配下にバイナリファイルが格納されます。

プロジェクトを作成する

  • ソースコード格納用のディレクトリの作成(任意)
mkdir $GOPATH/src
  • プロジェクトを作成
$ cd $GOPATH/src
$ bee new beego-app
$ cd  beego-app
$ ls
conf        controllers main.go     models      routers     static      tests       views
  • プロジェクトを起動
bee run

「アプリケーション“beego-app”へのネットワーク受信接続を許可しますか?」とアラートが表示されると思うが、許可をクリックして http://localhost:8080/ にアクセスして以下のような画面が表示されることを確認する。

localhost_8080.png

ここまでで以下のような構成のプロジェクトが作成されています。
それぞれの役割を詳しく確認したい場合は公式ドキュメントを見てみましょう。

.
├── beego-app
├── conf
│   └── app.conf
├── controllers
│   └── default.go
├── main.go
├── models
├── routers
│   └── router.go
├── static
│   ├── css
│   ├── img
│   └── js
│       └── reload.min.js
├── tests
│   └── default_test.go
└── views
    └── index.tpl

Dockerとdocker-composeでコンテナを立ち上げる

ホスト側でのBeego環境はできましたが、他開発者との共有を簡単に行うことができるようにDockerとdocker-composeを使ってコンテナ環境を立ち上げましょう。

docker-compose.ymlの作成

以下のファイルをプロジェクト直下に配置する

$ touch $GOPATH/src/beego-app/docker-compose.yml
docker-compose.yml
version: '3'
services:
  app:
    container_name: beego-app
    build:
      context: docker
      dockerfile: Dockerfile
    volumes:
      - .:/go/src/beego-app
    ports:
      - 10080:10080

portが他コンテナやサービスにバッティングしてしまう場合は、そのポートをlsofコマンドで確認してkillするかportsのところを任意に書き換えてください。
buildで記載されているcontext直下のDockerfileをビルドします。

docker-compose について詳しく知りたい場合
http://docs.docker.jp/compose/compose-file.html

Dockerfileの作成

dockerというディレクトリを作成してDockerfileを追加します。
Dockerfileについてはこちら

mkdir $GOPATH/src/beego-app/docker
touch $GOPATH/src/beego-app/docker/Dockerfile
# @see::https://hub.docker.com/_/amazonlinux
FROM amazonlinux:2

# システムアップデート
RUN yum update -y

# gitのインストール
RUN yum install -y git

# @see::https://fedoraproject.org/wiki/EPEL
RUN amazon-linux-extras install -y epel

# amazon-linux-extrasでインストールできる最新のgolang
RUN amazon-linux-extras list | grep golang
RUN amazon-linux-extras install -y golang1.11
RUN go version

# beegoのインストール
ENV GOPATH /go
ENV PATH $PATH:$GOPATH/bin
RUN go get -u github.com/beego/bee
RUN go get -u github.com/astaxie/beego

# カレントディレクトリをコンテナに追加する
COPY . /go/src/beego-app

# 作業ディレクトリを指定する
WORKDIR /go/src/beego-app

# コンテナ実行時にコンパイルと実行を行う
CMD bee run

イメージはAWS EC2での運用を想定してamazonlinux:2を用いている。
amazonlinuxベースのコンテナ上にgoとbeegoをインストールし、ホスト側をコンテナ側にマウントし最後にbeegoを実行しています。

コンテナを起動する

コンテナを立ち上げる前に上記のDockerfileのportをmain.goのbeego.Runの引数に渡します。

main.go
package main

import (
    _ "beego-app/routers"
    "github.com/astaxie/beego"
)

func main() {
    beego.Run(":10080")
}

Dockerfileをビルドしてコンテナを起動します。
docker-compose.ymlのディレクトリで以下のコマンドを実行します。

$ docker-compose up -d
Creating network "beego-app_default" with the default driver
Building app
Step 1/14 : FROM amazonlinux:2
2: Pulling from library/amazonlinux

正常に起動できているかpsコマンドで確認してみましょう。

$ docker-compose ps           
  Name           Command         State            Ports          
-----------------------------------------------------------------
beego-app   /bin/sh -c bee run   Up      0.0.0.0:10080->10080/tcp

コンテナの中に入って見てみましょう。

$ docker exec -it beego-app bash
bash-4.2# ls
beego-app  conf  controllers  docker  docker-compose.yml  main.go  models  routers  static  tests  touch  views
bash-4.2# pwd
/go/src/beego-app

もし、うまくいかなくてクリーンな状態からやり直したい場合、 docker-compose down --rmi all --volumes で該当のコンテナ、ネットワーク、ボリューム、イメージだけを削除するか、
もし他のコンテナやイメージもリセットしてしまって良い場合はdockerのアプリケーションを起動してpreferencesから「Reset disk image」で完全にリセットしてしまう方法もあります。

上記うまく行っていたらコンテナの実行ログを見てみましょう。

$ docker logs -f beego-app
______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v1.10.0
2020/02/09 10:21:09 INFO     ▶ 0001 Using 'beego-app' as 'appname'
2020/02/09 10:21:10 INFO     ▶ 0002 Initializing watcher...
beego-app/controllers
beego-app/routers
beego-app
2020/02/09 10:21:12 SUCCESS  ▶ 0003 Built Successfully!
2020/02/09 10:21:12 INFO     ▶ 0004 Restarting 'beego-app'...
2020/02/09 10:21:12 SUCCESS  ▶ 0005 './beego-app' is running...
2020/02/09 10:21:12.975 [I] [asm_amd64.s:1357]  http server Running on http://:10080

http server Running on http://:10080 というところに着目して、10080番ポートにリッスンされていることが確認できたので以下にアクセスして確認してみます。

http://localhost:10080/

ホスト側の時と同じ画面が表示されたら成功。
localhost_10080_.png

CircleCIでCI環境を構築する

最近ではgithub actionsなども出てきているが、とはいえCircleCIを採用している現場もまだまだ多いとおもうので、ここではCircleCIを用いてCI「Continuous Integration(継続的インテグレーション)」環境を構築する。

config.ymlの作成

プロジェクト直下に .circleci というディレクトリを作成し、.circleci直下にconfig.ymlを置く。

$ mkdir $GOPATH/src/beego-app/.circleci
$ touch $GOPATH/src/beego-app/.circleci/config.yml

config.ymlを以下のように作成する

config.yml
# @see::https://circleci.com/docs/ja/2.0/configuration-reference/
version: 2.1


# 実行処理は 1 つ以上の名前の付いたジョブで構成され、それらのジョブの指定は jobs マップで行います。
jobs:
  # CircleCI上のテスト
  test:
    docker:
      - image: circleci/golang:latest
    steps:
      - checkout
      - run: echo "this is jobs"


# Workflow は、ジョブの集まりとその実行順序の定義に関するルールを決めるものです。
workflows:
  build-test-deploy:
    jobs:
      # CircleCI上のテスト
      - test

細かい定義は公式を確認してください。
今回はとりあえず最低限の定義のみ記載します。

実運用ではCircleCI上でテストコードを実行したり、特定のブランチ(masterやstagingなど)のときにデプロイを行い自動化するようなCD「Continuous Delivery(継続的デリバリー)」を実現したりします。

上記ではworkflowsからtestというjobsが実行され、jobsのtestで指定されているdockerイメージ上でstepsに記載されているコマンドが実行されます。

CircleCIにリポジトリを登録する

まずは上記のソースコードを各自のgithub上にリポジトリを作成します。
git?github?な方はこちらや他の記事などもググって参考にしながら進めてみてください。
リポジトリが作成できたらローカルで作成したソースコードをプッシュしましょう。

github.com_kqxgy385_cuddly-octo-meme (1).png

リポジトリの準備ができたらCircleCIに連携しましょう。
CircleCIのアカウントがない場合は https://circleci.com/ からgithubアカウントでサインアップしましょう。

ログインできたらAdd Projectsを見つけて該当のリポジトリの「Set Up Projects」を実行しましょう。
onboarding.circleci.com_project-dashboard_github_kqxgy385.png

既に.circleci/config.ymlを作成しているのでそのままStart Buildingしましょう
onboarding.circleci.com_project-setup_github_kqxgy385_cuddly-octo-meme.png

確認されますがStart Buildingしましょう
onboarding.circleci.com_project-setup_github_kqxgy385_cuddly-octo-meme (1).png

STATUSがRUNNINGからSUCCESSになれば成功です
app.circleci.com_github_kqxgy385_cuddly-octo-meme_pipelines.png

中に入るとSTEPSの詳細が確認できます
app.circleci.com_github_kqxgy385_cuddly-octo-meme_pipelines (1).png

これでプッシュされるたびにconfig.ymlに記載されている内容がcircleci上で実行されます。

フロントエンド環境を構築する

npm(Node Package Manager)でフロントエンドのパッケージを一括管理します。
npmが使えるかどうかは以下のコマンドで確認します。

npm -v && node -v

npmがない場合はまずnode.jsをインストールします。
node.jsをインストールすると一緒についてきます。
node.jsは公式から直接ダウンロードするか、homebrewを使ってダウンロードする方法があります。

参考
https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09

初期化

プロジェクトのルートディレクトリで以下のコマンドを実行します。

npm init

すると以下のようにコマンドラインでいくつか質問されると思います。
特にこだわりがなければ全てenterでいいです。

package name: (beego-app) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: (https://github.com/kqxgy385/cuddly-octo-meme.git) 
keywords: 
author: 
license: (ISC) 
Is this OK? (yes) 

するとpackage.jsonというファイルが生成されると思います。
npmでインストールしたパッケージのバージョン情報がpackage.jsonに格納されます。

以下のような内容になっていると思います。

package.json
{
  "name": "beego-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "directories": {
    "test": "tests"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kqxgy385/cuddly-octo-meme.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/kqxgy385/cuddly-octo-meme/issues"
  },
  "homepage": "https://github.com/kqxgy385/cuddly-octo-meme#readme"
}

先ほどのコマンドラインで回答した内容が反映されるようになっています。
作り直したい場合は一度package.jsonを削除してもう一度npm initしてみましょう。

scriptsというところでコマンドを定義しておくことが可能で、デフォルトではtestというechoしてexitするだけのスクリプトが定義されています。
ためしに npm run test と実行してみましょう。
今後ここにjsやcssなどのbuildのコマンドを定義して利用します。

パッケージの復元

package.jsonが置いてあるプロジェクトルートで以下のコマンドを実行します。

npm install

するとpackage.jsonに記載されている依存関係がインストールされ、package-lock.jsonというファイルが生成されます。

パッケージのインストール

必要パッケージのインストール方法を確認します。
以下のコマンドを実行してみます。

npm install webpack

するとnode_modulesというディレクトリが生成され、またpackage.jsonに以下のように追記されていると思います。

package.json
  "dependencies": {
    "webpack": "^4.41.6"
  }

これでプロジェクト内でwebpackを利用することができます。
必要なパッケージはnpm installでインストールしていきます。
node_modulesは一般的にgit管理するものではないのでgitignoreに入れておきましょう。

webpackでフロントエンドをバンドルできるようにしよう

ここから先は細かい説明は省略します。
package.jsonのscriptsとdependenciesを以下にします。

package.json
  "scripts": {
    "dev": "webpack-dev-server --config webpack.config.js",
    "webpack": "webpack --config webpack.config.js"
  },
  "dependencies": {
    "css-loader": "^3.4.0",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^5.0.2",
    "html-webpack-plugin": "^3.2.0",
    "node-sass": "^4.13.0",
    "sass-loader": "^8.0.0",
    "style-loader": "^1.1.2",
    "vue": "^2.6.11",
    "vue-loader": "^15.8.3",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.1",
    "write-file-webpack-plugin": "^4.5.1"
  }

プロジェクト直下にwebpack.config.jsというファイルを作成し、内容を以下にしてみましょう。
webpackについては公式をお勧めします。

webpack.config.js
const path = require('path');
const projectRoot = path.resolve(__dirname);
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const WriteFileWebPackPlugin = require('write-file-webpack-plugin');

module.exports = {
    // エントリーポイントを指定する
    entry: './static/js/entry/index.js',
    // bundleファイルをwebpackがどこにどのような名前で出力すればいいのかを指定する
    output: {
        filename: '[name].js',
        path: path.join(projectRoot, 'static/js/dist')
    },
    // webpack-dev-serverのオプションを選択する
    devServer: {
        // 使用するホストを指定する
        host: 'localhost',
        // リクエストをリッスンするポートを指定する
        port: '8000',
        // サーバーに提供するコンテンツを指定する
        contentBase: path.join(__dirname, "static/js/dist"),
    },
    // @see::https://webpack.js.org/configuration/devtool/
    devtool: "cheap-module-eval-source-map",
    // ローダーの設定
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.scss$/,
                use: ["style-loader", "css-loader", "sass-loader"]
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file-loader'
                    }
                ]
            },
        ]
    },
    // プラグインの設定
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'static/index.html')
        }),
        new WriteFileWebPackPlugin(),
    ]
};

バンドルされたファイルが static/js/dist に生成されるように設定されています。

ここまでできたらもう一度npm installします。

$ npm install

ここまででプロジェクトの構成は以下のようになっているかと思います。

.
├── README.md
├── conf
│   └── app.conf
├── controllers
│   └── default.go
├── docker
│   └── Dockerfile
├── docker-compose.yml
├── main.go
├── models
├── package-lock.json
├── package.json
├── routers
│   └── router.go
├── static
│   ├── css
│   ├── img
│   └── js
│       └── reload.min.js
├── tests
│   └── default_test.go
├── touch
└── views
    └── index.tpl

static直下にindex.htmlというファイルを生成し、内容を以下にしてみましょう。

<!DOCTYPE html>
<html lang="js">

<head>
  <title>beego-app</title>
</head>

<body>
  <div id="app" v-cloak></div>
</body>

</html>

jsというディレクトリの直下にentryというディレクトリとdistというディレクトリを作っておきます。
entryの直下にApp.vueというファイルを生成し、内容を以下にします。

<template>
  <div id="app" class="top">
    <header>
      <div class="title">
        <a href="/">BEEGO-APP</a>
      </div>
    </header>
  </div>
</template>

<script>
    export default {
        name: "app",
    };
</script>

<style lang="scss" scoped>
  .top {
    position: absolute;
    height: 1500px;
    width: 100%;
    background-color: #e8f0ff;
    top: 0;
    left: 0;

    header {
      display: flex;
      position: fixed;
      background-color: rgba(255, 255, 255, 0.9);
      height: 62px;
      width: 100%;
      z-index: 999;

      .title {
        display: block;
        position: relative;
        left: 10px;
        background-color: #d6e4ff;

        a {
          display: block;
          margin: 22px 0;
          color: #999999;
          cursor: pointer;
          text-decoration: none;

          &:hover {
            color: #da6b64;
          }
        }
      }
    }
  }
</style>

さらにentry直下にindex.jsというファイルを生成し、内容を以下にします。

index.js
import Vue from 'vue/dist/vue.esm.js'
import App from './App.vue'

new Vue({
    el: '#app',
    template: '<App/>',
    components: { App }
});

アプリケーションのデフォルトのアクセス先を変更するためrouters/router.goを以下に書き換えましょう。

router.go
package routers

import (
    "github.com/astaxie/beego"
)

func init() {
    beego.DelStaticPath("/static")
    beego.SetStaticPath("//", "static/js/dist")
}

ここまでできたらまずは以下のコマンドを実行してみましょう。

$ npm run webpack

先ほどpackage.jsonのscriptsで定義したwebpackを実行するコマンドのエイリアスです。
上記コマンドを実行して http://localhost:10080/ にアクセスして以下のような画面になっていれば成功です。
うまく行ってない場合はdocker-composeの再起動なども試してみましょう。

localhost_10080_.png

ここまでできたら次に以下のコマンドを試してみましょう。

$ npm run dev

先ほどpackage.jsonのscriptsで定義したwebpack-dev-serverを実行するコマンドのエイリアスです。

先ほどのwebpack.config.jsのdevServerのportを8000番にしたことにより http://localhost:8000 にアクセスできるようになります。
http://localhost:10080/ の時と同じ画面が見れていたら成功です。

今度はApp.vueの内容を適当に書き換えてみましょう。
npm run devを起動している最中はホットリロードが効いているはずなので、変更が即時で反映されていればwebpack.config.jsで設定した内容が反映されていることになります。

ここまでで構成は以下のようになります。

.
├── README.md
├── beego-app
├── conf
│   └── app.conf
├── controllers
│   └── default.go
├── docker
│   └── Dockerfile
├── docker-compose.yml
├── main.go
├── models
├── package-lock.json
├── package.json
├── routers
│   └── router.go
├── static
│   ├── css
│   ├── img
│   ├── index.html
│   └── js
│       ├── dist
│       │   ├── index.html
│       │   └── main.js
│       ├── entry
│       │   ├── App.vue
│       │   └── index.js
│       └── reload.min.js
├── tests
│   └── default_test.go
├── touch
├── views
│   └── index.tpl
└── webpack.config.js

次は?

デバッガツールdelveの導入、テストコード実行方法、MySQLコンテナを立ち上げてマイグレーションする方法などを追記します。そのうち。

参考
Getting started
https://beego.me/quickstart
Beego を触ってみる (環境構築)
https://qiita.com/macococo/items/e5ace2550418ccced9ac
Setting GOPATH
https://github.com/golang/go/wiki/SettingGOPATH
Compose ファイル・リファレンス
http://docs.docker.jp/compose/compose-file.html
npm入門
https://qiita.com/maitake9116/items/7825d90c09f3e2f87dea
webpack documentation
https://webpack.js.org/concepts/

hagyyyy
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした