もなかアイスの試食品

「とりあえずやってみたい」そんな気持ちが先走りすぎて挫折が多い私のメモ書きみたいなものです.

Ubuntuに.Net Core 3.1をインストールした話

はじめに

Dockerと.Net Core 3.1を使って開発をしたかったので、Ubuntuに.Net Core 3.1をインストールしてみた

環境

  • Ubuntu: 20.04.2 LTS
  • .Net Core 3.1

参考サイト

docs.microsoft.com

手順

パッケージリポジトリの追加

wgetのURLは、UbuntuのバージョンやDebianでも異なるので、参考サイトを確認するべし

$ wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb

SDKのインストール

$ sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-3.1

コマンドのバージョンを表示して、インストールされたか確認

$ dotnet --version
3.1.409

実際に使ってみた

UbuntuにJetBrains Riderをインストールして、Hello Worldを出力してみた

f:id:monakaice88:20210529204109p:plain

Riderのコンソール画面にちゃんとHello Worldが表示された

Riderは有料だけど、Visual Studio Codeなら無料で開発できそう

Go言語のゴルーチン・チャネルの使い方メモ

はじめに

何回かGo言語で処理を作ったことがあったけど、Go言語で並行処理を一切書いたことがなかったので、勉強がてら簡単な処理を書いてみることにした。

参考サイト

qiita.com

環境

並行処理しない

とりあえず並行処理していないコードを書いた

package sample

import (
    "fmt"
    "log"
    "time"
)

func NotUseGoRoutine() {
    log.Println("---------- Start Sample 01 ----------")
    process("first ", 10)
    process("second", 10)
    process("third ", 10)
    log.Println("----------  End Sample 01  ----------")
}

func process(name string, loopCount int) {
    commonLoopMessage(name, loopCount)
}

func commonLoopMessage(name string, loopCount int)  {
    for count := 1; count <= loopCount; count++ {
        time.Sleep(time.Second / 10)
        fmt.Printf("name: %s, loopCount: %d\n", name, count)
    }
}

出力

2021/05/28 06:49:38 ---------- Start Sample 01 ----------
name: first , loopCount: 1
name: first , loopCount: 2
name: first , loopCount: 3
name: first , loopCount: 4
name: first , loopCount: 5
name: first , loopCount: 6
name: first , loopCount: 7
name: first , loopCount: 8
name: first , loopCount: 9
name: first , loopCount: 10
name: second, loopCount: 1
name: second, loopCount: 2
name: second, loopCount: 3
name: second, loopCount: 4
name: second, loopCount: 5
name: second, loopCount: 6
name: second, loopCount: 7
name: second, loopCount: 8
name: second, loopCount: 9
name: second, loopCount: 10
name: third , loopCount: 1
name: third , loopCount: 2
name: third , loopCount: 3
name: third , loopCount: 4
name: third , loopCount: 5
name: third , loopCount: 6
name: third , loopCount: 7
name: third , loopCount: 8
name: third , loopCount: 9
name: third , loopCount: 10
2021/05/28 06:49:41 ----------  End Sample 01  ----------

並行処理する

さっきのコードを並行処理するように書き換える

並行処理が終わる前に関数を抜けないように、チャネルを使い、並行処理が終わるまでブロックする

参考サイトを見つつ修正

func UseGoRoutine01() {
    log.Println("---------- Start Sample 02 ----------")
    ch1 := make(chan bool)
    ch2 := make(chan bool)
    ch3 := make(chan bool)

    go processWithCh01(ch1, "first ", 10)
    go processWithCh01(ch2, "second", 10)
    go processWithCh01(ch3, "third ", 10)

    <- ch1
    fmt.Println("Receive ch1 message")
    <- ch2
    fmt.Println("Receive ch2 message")
    <- ch3
    fmt.Println("Receive ch3 message")

    log.Println("----------  End Sample 02  ----------")
}

func processWithCh01(ch chan bool, name string, loopCount int) {
    commonLoopMessage(name, loopCount)
    ch <- true
}

出力

2021/05/28 06:49:41 ---------- Start Sample 02 ----------
name: second, loopCount: 1
name: third , loopCount: 1
name: first , loopCount: 1
name: second, loopCount: 2
name: third , loopCount: 2
name: first , loopCount: 2
name: third , loopCount: 3
name: second, loopCount: 3
name: first , loopCount: 3
name: third , loopCount: 4
name: first , loopCount: 4
name: second, loopCount: 4
name: second, loopCount: 5
name: third , loopCount: 5
name: first , loopCount: 5
name: first , loopCount: 6
name: second, loopCount: 6
name: third , loopCount: 6
name: third , loopCount: 7
name: second, loopCount: 7
name: first , loopCount: 7
name: first , loopCount: 8
name: third , loopCount: 8
name: second, loopCount: 8
name: third , loopCount: 9
name: second, loopCount: 9
name: first , loopCount: 9
name: first , loopCount: 10
Receive ch1 message
name: second, loopCount: 10
Receive ch2 message
name: third , loopCount: 10
Receive ch3 message
2021/05/28 06:49:42 ----------  End Sample 02  ----------

ちょっと修正

チャネルは破棄できるらしい。(チャネルの戻り値を無視することではなく、チャネルをメモリから破棄的な意味)

チャネル破棄について調べると以下のサイトを発見

hori-ryota.com

チャネルを使う場合、以下の注意点があるらしい(他にもあるだろうけど)

  • 破棄したチャネルにイベントを送ると panic する
  • チャネルを多重に破棄すると panic する
  • 受信が先にいなくなるとブロックし続ける

また「処理が終了したこと」のみを通知する場合、チャネルに使用する型は「struct{}」で良いらしい

「struct{}」のサイズが「0」なので、通知のデータサイズが無いことを明示できる

qiita.com

func UseGoRoutine02() {
    log.Println("---------- Start Sample 03 ----------")
    ch1 := make(chan struct{})
    ch2 := make(chan struct{})
    ch3 := make(chan struct{})

    go processWithCh02(ch1, "first ", 10)
    go processWithCh02(ch2, "second", 10)
    go processWithCh02(ch3, "third ", 10)

    <- ch1
    fmt.Println("Receive ch1 message")
    <- ch2
    fmt.Println("Receive ch2 message")
    <- ch3
    fmt.Println("Receive ch3 message")

    log.Println("----------  End Sample 03  ----------")
}

func processWithCh02(ch chan struct{}, name string, loopCount int) {
    commonLoopMessage(name, loopCount)
    close(ch)
}

出力

2021/05/28 06:49:42 ---------- Start Sample 03 ----------
name: second, loopCount: 1
name: first , loopCount: 1
name: third , loopCount: 1
name: second, loopCount: 2
name: first , loopCount: 2
name: third , loopCount: 2
name: third , loopCount: 3
name: second, loopCount: 3
name: first , loopCount: 3
name: first , loopCount: 4
name: third , loopCount: 4
name: second, loopCount: 4
name: second, loopCount: 5
name: first , loopCount: 5
name: third , loopCount: 5
name: third , loopCount: 6
name: second, loopCount: 6
name: first , loopCount: 6
name: first , loopCount: 7
name: third , loopCount: 7
name: second, loopCount: 7
name: second, loopCount: 8
name: first , loopCount: 8
name: third , loopCount: 8
name: third , loopCount: 9
name: first , loopCount: 9
name: second, loopCount: 9
name: third , loopCount: 10
name: second, loopCount: 10
name: first , loopCount: 10
Receive ch1 message
Receive ch2 message
Receive ch3 message
2021/05/28 06:49:43 ----------  End Sample 03  ----------

MongoDBをDockerでつかってみた話

はじめに

とある案件で、DBの正規化が面倒臭そう&ちょっとの間だけしか利用しないシステムだったので、RDBSではなくNoSQLを使用することにした。

MongoDBをDockerで使用して見たところ、認証周りがイマイチ分からなかったので、自分がやったことをまとめ

環境

  • Docker: 20.10.6, build 370c289
  • docker-compose: 1.29.1, build c34c88b2
  • MongoDB: 3.4.4

参考サイト

qiita.com

MongoDBの構築

LinuxからMongoDBサーバを構築するのは面倒臭いので、Dockerから使用してみることにした。

docker-compose.ymlのは以下の感じ

version: '3'
services:
    mongo:
        image: mongo:3.4.4
        container_name: sample-mongo-db
        ports:
            - 27017:27017
        volumes:
            - ./mongo/db:/data/db
            - ./mongo/configdb:/data/configdb
        environment:
            MONGO_INITDB_ROOT_USERNAME: sampleAdmin
            MONGO_INITDB_ROOT_PASSWORD: thisIsTest
            MONGO_INITDB_DATABASE: sample-db
            TZ: Asia/Tokyo

MongoDBのイメージのバージョンは3.4.4

AWSのMongoDBのイメージ(AMI)が3.4.4のため

MongoDBの認証

コンソールから認証するときに、結構つまずいたのでメモ書き

$ mongo

使用するDBの切り替え

use admin

認証

db.auth("sampleAdmin", "thisIsTest")

認証に成功すると「1」、失敗すると「0」と返される

ユーザの追加

adminのログインを済ませた状態でDBの切り替え、「sample-db」を読み書きするユーザを追加する

use sample-db
db.createUser({
    user: "sample-app-user",
    pwd: "S@mple",
    roles: [
        { role: "readWrite", db: "sample-db" }
    ]
})

コンソール画面からコレを入力するのは面倒臭いね・・・

ユーザの自動追加

「/docker-entrypoint-initdb.d」というディレクトリに、.jsか.shファイルを置いておくと、自動的にスクリプトが実行され、ユーザの追加とかできるらしい

docker-compose.ymlに「/docker-entrypoint-initdb.d」のマウント設定を追加

version: '3'
services:
    mongo:
        image: mongo:3.4.4
        container_name: sample-mongo-db
        ports:
            - 27017:27017
        volumes:
            - ./mongo/db:/data/db
            - ./mongo/configdb:/data/configdb
            - ./mongo/init:/docker-entrypoint-initdb.d
        environment:
            MONGO_INITDB_ROOT_USERNAME: sampleAdmin
            MONGO_INITDB_ROOT_PASSWORD: thisIsTest
            MONGO_INITDB_DATABASE: sample-db
            TZ: Asia/Tokyo

ユーザを追加するスクリプト

var users = [
    {
        user: "sample-app-user",
        pwd: "S@mple",
        roles: [
            { role: "readWrite", db: "sample-db" }
        ]
    }
];

users.forEach(user => {
    db.createUser(user);
});