Believe you can

If you can dream it, you can do it.

LinuxでもWindowsコンテナ使いたいんじゃ

DockerでWindowsコンテナを使うためにはホストOSがWindowsである必要がある。
そもそもWindowsコンテナを必要とする人がWindowsを使っていることが珍しいと思うのですが、どうなんでしょう?

ということで、タイトルにある通りLinux上でもWindowsコンテナを使うことができないかと調べた結果、次のようなリポジトリを発見したので試していこうと思います。
コレ自体はMacOS上で利用することを想定していると思うのですが、LinuxUbuntu)でも行けるはず。。。

github.com

動作イメージとしては、VirtualBox上のWindowsにインストールされたDockerにホストOS(Linux)から接続を行い、Windows上で動いているWindowsコンテナにアクセスするそんな感じです。

環境

  • Ubuntu 22.04 LTS
  • VirtuallBox 6.1.34
  • Vagrant 2.2.19
  • Packer 1.6.1(必要に応じて)

Vagrant Boxのビルドを行い、VMを起動させる

※StefanSchererさんがVagrant Boxを用意してくれているので、実施しなくても問題ありません
※M1 Macでも動くWindowsが必要な場合は実施してもらえればです

Packerでビルドを行い、Windows Server 2019のVagrant Boxイメージを作成します。(Windows isoファイルが大きいので1時間以上かかります)

github.com

$ packer build --only=virtualbox-iso windows_2019_docker.json

しばらくするとVirtualBoxが起動してWindowsのインストールが始まると思います。DockerをインストールしたりWindowsUpdateを行ったりと色々行ってくれます。

windows_2019_docker_virtualbox.boxというファイルが作られます。

Vagrantを起動し、Docket contextでWindowsコンテナに切り替える

続いて次のリポジトリをCloneしてVagrant Boxを起動させます。

github.com

$ vagrant up --provider virtualbox 2019-box
Bringing machine '2019-box' up with 'virtualbox' provider...
==> 2019-box: Box 'StefanScherer/windows_2019_docker' could not be found. Attempting to find and install...
    2019-box: Box Provider: virtualbox
    2019-box: Box Version: >= 0
==> 2019-box: Loading metadata for box 'StefanScherer/windows_2019_docker'
    2019-box: URL: https://vagrantcloud.com/StefanScherer/windows_2019_docker
==> 2019-box: Adding box 'StefanScherer/windows_2019_docker' (v2021.05.15) for provider: virtualbox
    2019-box: Downloading: https://vagrantcloud.com/StefanScherer/boxes/windows_2019_docker/versions/2021.05.15/providers/virtualbox.box
==> 2019-box: Box download is resuming from prior download progress
==> 2019-box: Successfully added box 'StefanScherer/windows_2019_docker' (v2021.05.15) for 'virtualbox'!
==> 2019-box: Preparing master VM for linked clones...
    2019-box: This is a one time operation. Once the master VM is prepared,
    2019-box: it will be used as a base for linked clones, making the creation
    2019-box: of new VMs take milliseconds on a modern system.
==> 2019-box: Importing base box 'StefanScherer/windows_2019_docker'...
==> 2019-box: Cloning VM...
==> 2019-box: Matching MAC address for NAT networking...
==> 2019-box: Checking if box 'StefanScherer/windows_2019_docker' version '2021.05.15' is up to date...
==> 2019-box: Setting the name of the VM: windows-docker-machine_2019-box_1653714059442_57360
==> 2019-box: Clearing any previously set network interfaces...
==> 2019-box: Preparing network interfaces based on configuration...
    2019-box: Adapter 1: nat
    2019-box: Adapter 2: hostonly
==> 2019-box: Forwarding ports...
    2019-box: 3389 (guest) => 3389 (host) (adapter 1)
    2019-box: 5985 (guest) => 55985 (host) (adapter 1)
    2019-box: 5986 (guest) => 55986 (host) (adapter 1)
    2019-box: 22 (guest) => 2222 (host) (adapter 1)
==> 2019-box: Running 'pre-boot' VM customizations...
==> 2019-box: Booting VM...
==> 2019-box: Waiting for machine to boot. This may take a few minutes...
    2019-box: WinRM address: 127.0.0.1:55985
    2019-box: WinRM username: vagrant
    2019-box: WinRM execution_time_limit: PT2H
    2019-box: WinRM transport: negotiate
==> 2019-box: Machine booted and ready!
==> 2019-box: Checking for guest additions in VM...
==> 2019-box: Configuring and enabling network interfaces...
==> 2019-box: Mounting shared folders...
    2019-box: /home/chichi1091 => /home/chichi1091
==> 2019-box: Running provisioner: shell...
    2019-box: Running: scripts/create-machine.ps1 as C:\tmp\vagrant-shell.ps1

VirtualBoxを起動してみるとWindowsが起動していることがわかります。

$ docker context ls
NAME        DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
2019-box    2019-box windows-docker-machine           tcp://192.168.59.90:2376                            
default *   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm

Docker Engineにも追加されています。ではWindows上で動いているDockerに切り替えを行います。

$ docker context use 2019-box
2019-box
Current context is now "2019-box"

$ docker version
Client: Docker Engine - Community
 Version:           20.10.16
 API version:       1.41
 Go version:        go1.17.10
 Git commit:        aa7e414
 Built:             Thu May 12 09:17:30 2022
 OS/Arch:           linux/amd64
 Context:           2019-box
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
  API version:      1.41 (minimum version 1.24)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:45:40 2021
  OS/Arch:          windows/amd64
  Experimental:     false

OS/Archwindows/amd64になっています!これでLinux Dockerが Windows Docker Engineとつながっている状態です。
元の状態に戻す場合は以下のコマンドを実行してください。

$ docker context use default

Windowsコンテナへの接続

以下のコマンドを実行することで、VirtualBoxWindowsで起動しているWindowsコンテナに接続することができます。

$ docker run -it -v C:$(pwd):C:$(pwd) mcr.microsoft.com/windows/servercore:1809 powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved. 

PS C:\> 

PowerShellが起動しました!しかもホストOSのディレクトリもちゃんとマウントされています。
VirtualBoxWindowsにいろいろなWindowsコンテナを入れておけばLinuxからも操作することができます。予想される利用方法はiisが多いのかな?開発はLinuxMacで行って動かすのはiisというのは意外とありそうな気がします。

M1 Macの場合はVirtualBoxが利用できないので変わりにParallelsを使えばイケそうな感じですね。
README.mdに書いてある内容をそのまま行ってみましたが、いろいろな可能性を秘めていて楽しそうです。

全文検索システムを作りたい〜構想編〜

こんにちは、GWが始まって10連休の方も多いのではないでしょうか。
転職したばかりとはいえ、有給が付与されているのでお休みも取れるのですがカレンダー通りです。

先週からWEB+DB PRESSやSoftware Designといった雑誌を紙で購入しているのですが、本棚にびっしり配置されていてだいぶ場所が取られてしまっています。自宅にある設備で自炊が可能なのではと思い、調べてみたらスキャンを1ページ1ページ自分で行えばPDFを作ることが可能とわかったので自炊を始めています。

ただただPDFを作るだけでもいいのですが、せっかくなら全文検索できるようにして必要な情報にアクセスしやすいようにしたいと考えています。
ということで、システム構築みに向けて色々検討してみます。

要件

全文検索が行えること

ほしい情報やキーワードで調べることができないとせっかく電子化した意味はないかなと考えています。なので、全文検索が行えることが必須条件となります。

WEBシステムであること

全文検索が入ることで必然的にWEBシステムというのも必須条件となっていきますかね。

コストはかけない

僕はお小遣い制です。結婚してからビタ一文もお小遣いが上がっていないのでできる限りコストは抑えることとします。

出先でも利用できること

出先でも利用できることを目標としたい。必須としないのは「コストをかけない」が難しくなるからです。費用対効果を見ながら検討していきます。

実現方法

自作でシステム構築

勉強も兼ねて自力でシステムを構築している方法。
ほしい機能や仕組みを実現できる反面、いつ出来上がるか全く予想できないので計画が頓挫してしまう恐れがある。

なんらかのOSSを利用する

全文検索OSSで提供しているものを利用する方法。
ほしい機能や仕組みがあるかは運次第になってしまうものの、すぐにでもサービスを立ち上げることが可能になる。

結論

悩むこともなく「なんらかのOSSを利用する」で進んでみようと思います。思い浮かぶのはFESSぐらいなので、他に何があるのか調査からしていくことにします。オススメのOSSがあればコメントください。

3/19(土) 日報

3/19(土)の日報です。土日祝は休んでもいい気がしたが、せっかくなので続けてみる
日報はnoteにしようか悩み中

起床

  • いつも通りサプリ摂取
  • コーヒー飲みつつ洗濯物
  • ダラダラ

レーニングから昼食まで

  • 腹筋ローラー20回3セット
  • フィットネスバイク30分
  • 前職の上司から欲しいものリストのコカコーラゼロが届く!あざます!!
  • オイコスで朝食
  • ダラダラ
  • ちょっと読書

昼食から夕食まで

  • いつもと変わらない昼食(オートミール
  • ダラダラ
  • 買い物へ
  • 洗濯物取り込み
  • 夕食

夕食から就寝

  • 洗い物
  • TV見ながら団らん
  • ちょっと読書
  • 風呂

明日の予定&やりたいこと

  • [重要]執筆作業
  • 読書
  • SmartHRに入社情報入力
  • バリカン(坊主)
  • バイク自賠責加入とバッテリー用意
  • 服買いに行きたい

3/18(木) 日報

3/18(金)の日報
冬に戻ったような天気で寒い。。お休みも残り2週間で進捗が滞っていてヤバいな
次男が車の運転を披露してくれないので4月から通学できるのか心配だ。。

起床

  • マンガアプリを読む
  • 雇用時受入健康診断の受診
  • 住民票を貰いに支所へ

運動

  • スクワット:120回
  • フィットネスバイク:30分
  • オイコスで朝食

昼食から夕方

  • 執筆原稿の赤入れdone
  • 入社時のティータイムセットの住所入力
  • ちょっと読書
  • 昼食
  • 洗い物
  • ボケーと過ごす
  • 入社前面談
  • 娘を塾へ送迎
  • SmartHRに入力
    • 扶養部分がわからず。。総務に追加質問

夕食から就寝

  • 夕食
  • 洗い物
  • ボケーと過ごす
  • 執筆作業

明日の予定&やりたいこと

3/17(木) 日報

3/17(木)の日報です。
昨日に比べてちょっと肌寒い。。

起床

  • サプリを摂りつつ、コーヒーを落とす
  • ゴミ捨て
  • マンガアプリを読む
  • コーヒーを飲みつつ洗濯物を干す
  • ボケーとする

運動

  • 腕立て伏せ:15回ぐらい
  • 膝立ちの腕立て伏せ:10回4セット
  • フィットネスバイク:30分
  • オイコスで朝食

昼食・ダラダラ

  • 妻はお友だちとランチにお出かけ
  • コンビニへ買い物
  • 読書
  • ブログ
  • ダラダラ
  • 車の運転練習(次男)
  • 散歩がてらダイソーで買い物
  • 洗濯物取り入れ
  • 執筆赤入れ

夕食から就寝

  • 上田に酒井さんが来てると聞くがさすがに行けぬ。。

  • 夕食
  • 洗い物
  • 娘に背中を踏んでもらう
  • 星街すいせいの配信見る
  • 執筆赤入れ
    • 終わらず。。。
  • 風呂
  • SmartHRに入社情報入力
    • 終わらず。。。

明日の予定&やりたいこと

明日はちょっと忙しいかな

  • [重要]健康診断
  • [重要]入社前面談
  • [重要]住民票入手
  • [重要]執筆作業
  • [重要]SmartHRに入社情報入力
  • 読書
  • バリカン(坊主)
  • バイク自賠責加入とバッテリー用意
  • 服買いに行きたい

サーバサイドKotlinでKomapperを使ってみよう

Kotlin製ORマッパーのKomapperが5月に1.0のリリースされると聞いてSpringBoot上で試してみました。といってもサンプルソースも豊富なのでそれに毛が生えた程度です。。

CRUD

H2を利用してpersonテーブルを用意してCRUDを動かします。

create table person
(
    id    int GENERATED ALWAYS AS IDENTITY (START WITH 3) PRIMARY KEY,
    name  varchar(255) not null,
    email varchar(255) not null
);

エンティティ、マッピング定義

テーブルと対になるエンティティとPKなどの項目にアノテーションを定義して項目マッピングを行います。

data class Person(
    val id: Int? = null,
    val name: String,
    val email: String,
)

@KomapperEntityDef(Person::class)
data class PersonDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

クエリ実行

QueryDSLを利用してSQLを実行します。メソッドチェーンでやりたいことをつなげていく感じなので直感的でわかりやすいですね。

@Service
class PersonService(
    private val database: JdbcDatabase
    ) {
    fun findAll(): List<Person> {
        return database.runQuery {
            val p = Meta.person
            QueryDsl.from(p).orderBy(p.id)
        }
    }

    fun findById(id: Int): Person {
        return database.runQuery {
            val p = Meta.person
            QueryDsl.from(p).where{ p.id eq id }.first()
        }
    }

    @Transactional
    fun insert(name: String, email: String): Person {
        return database.runQuery {
            val person = Person(name = name, email = email)
            val p = Meta.person
            QueryDsl.insert(p).single(person)
        }
    }

    @Transactional
    fun update(id: Int, name: String, email: String): Person {
        return database.runQuery {
            val person = findById(id)
            val p = Meta.person
            QueryDsl.update(p).single(person.copy(name = name, email = email))
        }
    }

    @Transactional
    fun delete(id: Int) {
        database.runQuery {
            val person = findById(id)
            val p = Meta.person
            QueryDsl.delete(p).single(person)
        }
    }
}

結合

テーブル結合をしたSQLも試してみます。チームテーブル、チームメンバーテーブルを用意して、personテーブルを含めた3テーブルの結合を行います。
DDLは次の通りです。

create table team
(
    id   int GENERATED ALWAYS AS IDENTITY (START WITH 3) PRIMARY KEY,
    name varchar(255) not null
);

create table team_member
(
    id        int GENERATED ALWAYS AS IDENTITY (START WITH 4) PRIMARY KEY,
    team_id  int not null,
    member_id int not null
);

エンティティとマッピング

data class Team(
    val id: Int? = null,
    val name: String,
)

@KomapperEntityDef(Team::class)
data class TeamDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

data class TeamMember(
    val id: Int? = null,
    val teamId: Int,
    val memberId: Int,
)

@KomapperEntityDef(TeamMember::class)
data class TeamMemberDef(
    @KomapperId
    @KomapperAutoIncrement
    val id: Nothing,
)

left joinを行います。leftJoinメソッドで結合するテーブルを指定し、selectメソッドで取得するカラムを指定します。

@Service
class TeamService(
    private val database: JdbcDatabase
) {
    fun findById(id: Int): TeamDTO? {
        val g = Meta.team
        val m = Meta.teamMember
        val p = Meta.person
        val result = database.runQuery {
            QueryDsl.from(g)
                .leftJoin(m) { g.id eq m.teamId }
                .leftJoin(p) { m.memberId eq p.id }
                .where { g.id eq id }
                .orderBy(m.id)
                .select(g.id, g.name, p.id, p.name, p.email)
        }

        val members = result.map {
            Member(it[p.id]!!, it[p.name]!!, it[p.email]!!)
        }
        val member = result.first()
        val id = member[g.id]
        val name = member[g.name]

        return TeamDTO(id!!, name!!, members)
    }
}

完成したソースは↓です。

github.com

感想

SQLをメソッドチェーンで組み立てていくことができるので悩まずに実装できるのがいいですね。アノテーションプロセッサーを利用しているのでMetaで指定できるテーブルはコンパイルをしていないと怒られてしまうのは注意が必要です。(大した問題ではないが)

R2DBCに対応しているORマッパーは少ないので採用候補に上がるプロジェクトも多いんじゃないでしょうか。
基本機能を試した程度ですが、これから採用実績は増えていくこと間違いなしだと思います!!

3/16(水) 日報

3月末までは充電期間のためお休みをいただいております。
就業までの間にお休みをいただく(有給消化的な)のは初めてで、ダラけた生活を送ってしまっているので日報を書くことでダラけない生活を送る努力をしてみようと思い、今日から日報を書いていこうと思います。

興味ないと思いますが、お付き合いいただければです <( )>

起床

  • サプリを摂りつつ、コーヒーを落とす
  • マンガアプリを読む
  • コーヒーを飲みつつ洗濯物を干す
  • ボケーとする

運動

  • 腹筋ローラー:20回を3セット
  • フィットネスバイク:30分
  • オイコスで朝食

昼食

  • 早めの昼食
  • 洗い物など

お出かけ

  • 妻を送迎
  • 娘とダラダラお出かけ
    • ペットショップはしご
    • アポ無しで実家に行く
    • 善光寺のすみっコぐらし堂でお買い物

  • 図書館でブラブラ
  • 妻のお迎え

帰宅〜夕食

  • 洗濯物取り入れ
  • 息子のお迎え
  • ボケーとする
  • 夕食

寝るまで

  • ブログ書く
  • 洗い物など
  • YouTubeライブの勉強会参加
  • Spring Boot+Kotlin+Komapperのサンプル実装
  • 風呂

明日やりたいこと

  • [重要]本の執筆
  • 読書
  • バリカン(坊主)
  • バイク自賠責加入とバッテリー用意
  • 服買いに行きたい