お世話になっております。
しゃまとんです😊

https って、Web上に置かないと出来ないものかと思っていたんですが、昨今はローカル環境もできるのですね。 ということでやってみました。

httpsとなると、オレオレ証明書とか作りたくないな〜…

みたいなこと思うのですが Github には素晴らしい OSS があるのです。
それが mkcert です。

使い方がめちゃくちゃ簡単で

mkcert -install
mkcert localhost

で証明書を作成してくれるのです。素晴らしいですね。
これで証明書をゲットしつつ、Docker + Go でちゃちゃっと https なサーバを公開していきましょう。 https はデフォルトポートが 443 なので、コードから直接 443 を設定しようとすると権限の都合で辛い場面に遭遇するので、publishする形でやっていこうと思います。

まず最初に Dockerfile を用意します。mkcertのバージョンはこちらで確認してくださいね。
(go.sumは今回ありませんでした)

FROM golang:1.17-buster

RUN apt-get update \
    && apt-get install -y libnss3-tools

RUN curl -LO https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64 \
    && chmod +x mkcert-v1.4.3-linux-amd64 \
    && mv mkcert-v1.4.3-linux-amd64 /usr/local/bin/mkcert

WORKDIR /work

RUN mkcert -install \
    && mkcert localhost 127.0.0.1 192.168.0.1

COPY go.mod .
#COPY go.sum .
COPY cmd cmd/

RUN CGO_ENABLED=0 GOOS=linux go build -v -o ./server ./cmd

CMD ["./server", "./localhost+2.pem", "./localhost+2-key.pem"]

Linux では libnss3-tool が必要なので install しつつ、 mkcert を使えるようにしていきます。 そして証明書を作業場で発行し、サーバをビルドして実行します。

サーバ(cmd/main.go) はこちら。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World")
}

func main() {

    if len(os.Args) < 2 {
        log.Fatal("crt and key must be set")
    }

    crt, key := os.Args[1], os.Args[2]

    cat(crt)
    cat(key)

    http.HandleFunc("/", handler)
    err := http.ListenAndServeTLS(":8080", crt, key, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


func cat(filename string)  {
    file, err := os.Open(filename)
    defer file.Close()

    data, err := ioutil.ReadAll(file)

    if err != nil {
        log.Panicln(err)
    }

    fmt.Println("==", filename, "==")
    fmt.Println(string(data))
}

これをおもむろにガッっと実行していきます!確認で pem の内容が出力されると思います。

# build
docker build -t gomkcert .

# run
docker run --publish 443:8080 --name gomkcertest --rm gomkcert 

# 以下は出力
== ./localhost+2.pem ==
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

== ./localhost+2-key.pem ==
-----BEGIN PRIVATE KEY-----
...
-----END CERTIFICATE-----

curl してみます。

curl -k https://localhost
Hello, World⏎

ブラウザでも、こんな感じですね〜(危険を承知で〜みたいなのは出るのね) image

今回のソースは shamaton/go-mkcert-sample にまとめております〜。
以上です〜👋

■ 参考