Code for final

ふぁいなる向けのコード置き場です。すでにコードじゃないこともいっぱい。

Windows10にDocker Desktop for WindowsをいれてLinuxコンテナで動かす手順(基本編)

Dockerについて以前調べたときに以下の記事を書いたのですが、その後時代は進んだようで、2020年5月現在でもっと簡単に構築できるようになっていたのでメモしておきます。

final.hateblo.jp

Dockerに関する誤解(Windows版だとLinuxのインストールが必要?)

まずわたしだけかもですが、Windows版のDockerを入れるとWindowsで動くので、Linux環境で動かすにはdockerでLinuxOSを入れて、LinuxOS内にdockerをいれてみたいな手順が必要で手間がかかると思っており、 Windows版を敬遠していましたが、それは大きな誤解でした。
その答えはWindows版をインストールしたらわかりました。Windows版のインストールはHyper-Vを有効にしておくことが必須なのですが、それはなぜかというとWindows版のインストール時にHyper-Vに"DockerDesktopVM"というDockerを動かすためだけのLinux環境が作成されます。
なのでWindowsコマンドプロンプトからdockerコマンドをたたいたら、実際は内部で動いてるLinuxの環境で実行されるというわけです。
というわけなのでLinux環境で動かしたい方も安心してWindows版を使ってください。(VirtualBoxCentOSを入れるより簡単で便利です)

Hyper-VはHomeエディションでは使えないのでWindows版は使えない?

Hyper-VはHomeエディションでは使えないことは有名な話だと思いますが、次のWindows10 2004(2020/05/04時点では未リリース)から"WSL2(Windows Subsystem for Linux(WSL) 2)"という機能(Hyper-Vと似たようなもの)がリリースされ、これを使うことでDocker Desktopを動作させることができるみたいです。気になる方はググってみてください。

Dockerとは?

Dockerに興味があるひとがこの記事にたどり着いていると思うので説明不要だと思いますが、簡単に言えば仮想サーバ構築ツールです。
VMと異なるのはサーバごとにOSのインストールは不要で、1つのサーバ上に複数のサーバの構築ができます。
構築したサーバはイメージ化して配布できるので誰がやっても同じ環境が構築できます。
また、各種サーバアプリ(ApacheMySQLなど)のイメージが公開されており、コマンド1つで構築可能です。
僕はインフラ周りはあまりやらないのですが、開発環境やテスト環境構築とかで使えると思います。

www.docker.com

それでは以下に手順を記載します。

Hyper-Vを有効化

Hyper-Vはデフォルトでは有効になっていません。
なのでPowerShellを管理者権限で起動して以下のコマンドを実行します。

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

インストールが終わったら再起動が促されます。手順に不安がある方は以下を参照してください。

docs.microsoft.com

Docker Desktop for Windowsをダウンロード

Docker公式サイトからDockerDesktop for Windowsをダウンロードします。
以下のサイトの"Docker Desktop"の"Download for Windows"をクリックするとダウンロードが始まります。 ファイルサイズは1GB近くあります。

www.docker.com

Docker Desktop for Windowsをインストール

ダウンロードした"Docker Desktop Installer.exe"を実行して、OKを押して次へ進むだけでOKです。
途中、"Use Windows containers instead of Linux containers (this can be changed after installation)"の チェックがOFFであることを確認してください。(デフォルトでOFFなので何もしなくてよいですが) これは訳すと"Linuxコンテナーの代わりにWindowsコンテナーを使用する"なのでチェックがOFFの場合Linuxコンテナで動作します。インストール後に切り替えも可能です。
インストールが終わると再起動が促されます。

Docker用の仮想環境がはいってることを確認 (この手順は省略可)

Windowsの再起動後、検索ボックスに"hyper-v"といれて"Hyper-V マネージャー"を立ち上げると以下のように "DockerDesktopVM"という仮想環境が構築されていることが確認できます。これがDockerを動かすためのLinux環境の正体です。

f:id:finalstream:20200503181903p:plain

Dockerコマンドを実行する

PowerShellを立ち上げて"docker version"をたたいて、バージョンが表示されればインストール成功です。
コマンドプロンプトでもOKですが、PowerShellのほうがシャットダウンしてもコマンドの履歴が残るので便利です。

> docker version
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b
 Built:             Wed Mar 11 01:23:10 2020
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       afacb8b
  Built:            Wed Mar 11 01:29:16 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

DockerでWEBサーバを構築

上記までの手順ではDockerのエンジンだけインストールされているのでこっから本領発揮のとこです。
試しにapache webサーバを構築してみます。 Dockerは各種アプリのイメージが公式的に公開されており、そのイメージをダウンロードしてローカルサーバで動かす仕組みとなってます。
どんなイメージがあるかは以下のサイトで確認できると思いますが、RedminePostgreSQL、Jenkinsなどわりとなんでもあります。

hub.docker.com

なので以下の"docker run"コマンドを流すだけで、apche webサーバーの構築ができてしまいます。
構築した環境はコンテナと呼びます。

> docker run -d -p 80:80 --name httpd httpd

オプションの意味を簡単に解説すると以下になります。

  • "-d"はバックグラウンドで動作させる(指定しないとコンソールが持っていかれる)
  • "-p 80:80"(ホスト:コンテナ)はポート転送設定(試しに8080:80にするとlocalhost:8080でアクセスできる)
  • "--name http"は名前を"httpd"にする。(指定しないとランダムでヘンテコな名前が命名される)
  • 最後の"httpd"はDocker Hubで公開されているイメージ名

起動したかは以下の"docker ps"コマンドで、httpdがいればOKです。

>docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                NAMES
1b38ad530ec1        httpd               "httpd-foreground"   2 minutes ago       Up 2 minutes        0.0.0.0:80->80/tcp   httpd

WEBサーバの起動を確認

Windowsからブラウザを起動して、"localhost"をアドレスバーにいれてたたくと さみしいapacheの初期画面がでれば起動しているということです。

f:id:finalstream:20200503183816p:plain

DockerをGUIで操作

Windows版ではDockerアプリのDashboardを開けば画面で確認できます。(タスクトレイのクジラのアイコンを右クリックでDashboardを選択)
緑になっていれば動いています。ここから停止とか削除もできます。便利ですね。

f:id:finalstream:20200503183452p:plain

さらにhttpdを選択すれば詳細が確認でき、アプリごとのログを確認できます。超便利。

f:id:finalstream:20200503190510p:plain

最後に

以前VirtualBoxを使った構築に比べたらだいぶ簡単に構築できました。マシンのスペックによりますが、30min以内でできるんじゃないでしょうか。
まだまだ奥が深いDockerですが、ここまでなんとなくDockerについてさらに手軽になった感じが伝わったかと思います。
ただ、実際の業務で使用するにはまだまだ必要な知識が足りないので、あと実践編としてまとめたいと思います。
では素敵なDockerライフを。

TypeScriptは難しくない。JavaScriptをやったことあればTypeScriptでシステム開発はすぐできる。メリットだらけなのでやったほうがいい。

ついこないだまでTypeScriptでシステム開発をってやってみたいけど 新しく覚えるの大変だろうな、覚えること多いんだろうなーって思って JavaScriptに逃げていました。
でも、思いきって今回仕事でTypeScriptを使って、システムのリリースまで終わったいまでは 絶対JavaScriptより、TypeScriptがいいって思います。

あとで詳しく書いていますが、TypeScriptでシステム開発しようと思って未経験者しか集まらなくても、 JavaScriptをやったことあれば、以下の2つだけ伝えればTypeScriptでシステム開発できますし、メリットだらけなのでやったほうがいいです。
現に今回やったシステム開発(20名くらい)で誰一人TypeScriptやったことあるひとはいませんでしたが、TypeScriptで開発できたので実証済みです。

  • 型推論できるものは型は書かない。わからないひとはエラーになったら型を書くこと。
  • 変数はまずconstで宣言する。変更する必要があるものはlet。varは使用禁止。わからないひとはconstでエラーになったらletにする。

TypeScriptが何者かご存じない方は、以下を見てもらえればわかりますが、 TypeScriptで書いたコードはビルドすることでJavaScriptに変換され、ブラウザで実行されます。
Microsoftが開発したものなので将来的にも安心して使えますし、導入するときに顧客に説明するときもMicrosoftが作ったものと言えばすんなり通るでしょう。

ja.wikipedia.org

わたしがTypeScriptを誤解していた点、良いと思う点についてまとめたいと思います。

誤解していた点

覚えないといけないことが多そう

コードを書くという点でいえばぜんぜん覚えることないです。
より便利にコーディングするために知ってたほうがいいことはいくつかありますが。
TypeScriptはJavaScriptに型が追加になったものと認識で問題ないとわたしは思います。
その型もプリミティブ型(基本の型)でいえばstring, number, booleanくらいしかありません。あと使うのは自分で作ったクラスです。
あとは変数宣言にはvarを使わずconstを使うくらいですかね。 また、細かい点はコードが間違っているとエディタが警告してくれるので始める前に学習しなくても自然と身につきます。

型を書かないといけないので逆にコード量が増えて大変そう

TypeScriptは型が追加になるってことくらいは知っているひとは多いと思います。
C#やったことあるひとならわかると思いますが、型推論があるのでそんなに気にしなくていいです。
型推論がわからないひとは以下のコードを見てもらえばと思います。
型をつける、つけないの判断できないのではないかと不安に思うひともいると思いますが、 ご安心ください。 つけないといけない場合はビルドエラーになるのでわかります。VSCodeが赤線を引いてくれます。

const id = ""; // string型と推論できるので型の記載は不要です。
const id; // 初期値から型推論できないので型が必要です。ビルドエラーになります。

書いたコードを見直しましたが、型を書いてたのはメソッドの引数と戻り値の宣言と独自のクラスにキャストするときくらいでした。
メソッドの引数と戻り値(ある場合)は必ず書いたほうがいいです。それがTypeScriptのいいところですから。
その理由は後述します。

自分だけコーディングできてもチーム全員できないとチーム開発では使えないのでは?

今回のプロジェクトでは20名ほどコーダーがいましたが、 誰一人TypeScriptを使ったことあるひとがいませんでした。存在すらしらなかった人が多かったです。
ただ、JavaScriptをやったことあるといったひとでした。
このご時世、JavaScriptをやったことないひとは新人くらいだと思います。
JavaScriptさえ知っていればチーム開発でもTypeScriptは全然使えます。
以下の3点だけ説明すればOKだとわたしは思います。
実際、今回の開発もこれでうまくいきました。

  • 型推論できるものは型は書かない。わからないひとはエラーになったら型を書くこと。
  • 変数はまずconstで宣言する。変更する必要があるものはlet。varは使用禁止。わからないひとはconstでエラーになったらletにする。
  • エディタ上で赤い線が出ているところは必ず修正する。(当たり前ですけど守られていないことがありました)

守らないひとがいてバラバラになるのでは?と危惧されると思いますが、エディタの設定で矯正できますし、 最終的にビルドのときにエラーになるのでわかります。

ビルド(コンパイル)環境を構築するのがめんどそう

JavaScriptはビルドする必要がないので、手軽さという点ではJavaScriptよりは劣ると思っていました。
これがわたしが一番敬遠する理由でした。
コマンドでビルドする仕掛けをバッチ処理で作る必要があるのかと思っていました。
ただ、Vue CLIを使うことでまったくビルドしている感じなく、 JavaScript同様に使えるので杞憂だったということがわかりました。
今回はVueだったのでVue CLIでしたが、ほかの環境でもきっと同じだと思います。

ビルドしたものを動かすからデバッグができないのでは?

デバッグはtsファイルにブレークポイントをつけて普通にできますのでご安心を。
デバッグのテクニックは後日記事を書きたいと思います。

良い点

タイプミスに早期に気づける

これが一番の魅力だと思います。IDEが発展してきてインテリセンスなどで だいぶタイプミスによるバグを軽減することができるようになりましたが、 完全にゼロにすることはできません。
TypeScriptではビルド時にチェックはもちろん、VSCodeだとエディタ上で 赤い線で警告することもできるので効率よくコーディングできます。

const userid = "a";
// 宣言が見えないくらい間があいている
alert(user_id); // ビルドエラーになる。user_idという変数は宣言されていないため

想定と違う型の値が入ることがない

JavaScriptだと型がないのでどんな値でも入るので 間違って違う型の値が入ってる可能性があるかもと心配することがあるかもしれませんが、 TypeScriptでは型があるので型に当てはまらないものは入りません。
また、使う機会は局所的ですが、any型というなんでも入る型もあります。

let value = "0"; // 型推論で文字列型になる。
value = 1; // 数値型はいれることができない。

メソッドに渡しているものが間違っていると警告してくれる

メソッドの引数と戻り値には必ず型を定義しますので、 間違った型の変数を渡したら赤で警告がでるのでコーディングミスが事前に防げます。
JavaScriptだと動かしてエラーになるまで気づけません。

function main() {
  this.add(1)
}

function addPrefix(value: string) :string {
  return "prefix" + string;
}

変数が変わってないことを保証してくれる

TypeScriptでは変数をconstで宣言することをおすすめします。
constは一般的に定数で使うキーワードですが、TypeScriptでは 一度いれたらインスタンスを変更できない変数として使います。
変更しようとしたら警告してくれるので間違いに気づけます。
変数って意外と一回入れたら変更しないものです。
今回開発したコードを見直しましたが、ほとんどconstでいけてました。
letを使ってたのはループ内変数くらいですね。
ちなみにconstでarrayを宣言してpushしてもエラーにはなりません。
インスタンスを変更していないので。

const numbers = [];
numbers.push(1); // ○ エラーにはならない。インスタンスを変更していないから。
numbers = []; // ✕ エラーになる

for (let i = 0; i < array.length; i++) { 
  // forで回すときはletを使う
}

メソッドの処理でnullやundefifnedチェック処理が不要になる

JavaScriptだとundefinedやnullが入ってこないかチェックする必要があったりしますが、 TypeScriptではnullとundefinedを型として扱うことができるので、 チェックする必要がなくコードがスッキリします。(HTMLとの境界のメソッドでは一部例外もありますが) 誤っていれたらエディタで赤い線が出るのでわかりやすいです。
もちろんnullを使いたいときは使うこともできます。

const value = ""; // string
const value :string = null; // ビルドエラーになる
const value :string | null = null; // nullをいれることができる

map型がある

システム開発ではよくmap型を使います。
JavaScriptにはmap型がなく、代替としてobjectをmapとして使ったりしますが、 TypeScriptでは標準でmap型があるので非常に便利です。

const idMap = new Map<string, number>();
idMap.set("a", 1);
idMap.set("b", 2);
idMap.forEach((value, key)=>{
  console.log(value); // mapを回すことも可能
});

クラスが使える

クラスもシステム開発では必須といっていいと思います。
データを定義するのに使います。
特に継承をうまく使って共通化したりすれば、品質も生産性もあがります。

export default class Home extends Base {

}

というようにいいことしかないのでこれからWEBシステムを開発するひとがいたら JavaScriptではなく、ぜひTypeScriptで開発してほしいと思います。

UiPathでzipファイルを解凍する。

最近、RPAについて勉強しています。
UiPathを使ってzip解凍をしたくなって、試していたのですが、ちょっとだけはまったので記録しときます。

UiPathには便利なアクティビティ(部品)がたくさんありますが、圧縮ファイルを解凍するアクティビティはまだないみたいです。
アンオフィシャルなものならあるかもですが。

なので7-zipを使って解凍することにします。

www.7-zip.org

7-zipをインストールしてある前提とします。

プロセスを開始アクティビティを配置して、以下のように設定します。

f:id:finalstream:20190920105719p:plain

プロパティ
ファイル名   "C:\Program Files\7-Zip\7z.exe"
引数 "x -y -o""" + rootPath + """ -p" + zipPassword + " """ + item.ToString() + """"

rootPathは解凍先、zipPasswordはzipファイルのパスワード、itemは解凍するzipファイルの変数です。

ポイントとしては以下の3つですかね。

  • "(ダブルクォーテーション)はエスケープ("で囲む)が必要
  • オプションとオプション値の間にスペースは入れない
  • 引数全体を"で囲む