Dockerfile を使って、自分用の Ubuntu の Docker イメージを作成する
前回の続き。
今回の目的
docker pull ubuntu
で最新版のubuntuイメージを取得することはできる。
しかし、その場合、 sudoすら入っていない状態なので、一つずつ apt-get
で環境整備する必要が出てくる。 そこで、Dcokerfile を使用して楽をする。
Dockerfile とは
イメージのカスタマイズをスクリプトで実現することができる。
Dockerfile を使用することで、物理的に異なるデバイスでも、同一の環境をすぐ用意できるようになる。たぶん。
Ubuntu 用の Dockerfile 導入手順
参考
前提
そもそも Docker を導入した最終目的は protobuf-cで遊ぶためのコンパイル環境を用意することである。
そのため、 Ubuntu 用の Dockerfile も protobuf-c のコンパイルのためにカスタマイズする。
- protobuf-c をコンパイルするために必要なもの一覧
- sudo
- autoconf
- automake
- libtool
- curl
- make
- g++
- unzip
- pkg-config
- protobuf(後述の注意の通り、apt-getで取得するのはNG)
- あと、あれば便利なもの一覧
- wget
- git
注意:protobuf-c と protobuf の互換性問題
現状、protobuf-c の最終リリース版(protobuf-c Ver1.30)自体に、本家 protobuf との互換問題があるらしい。
(protobuf Ver3.00 以上を用意しないと protobuf-c がコンパイルできない。しかし、Ubuntu 用の apt-get では protobuf のバージョンがVer2.6X らしいので、普通に本家 protobuf を用意するのではなく、自前で用意する必要がある)
上記を踏まえて Dockerfile を作る
そもそも、Dockerfileの置き場所はどこが適切なのか調べたが、ぱっと出てこない。
たぶん、どこでもいいような気がするので、今回はDocker ToolBox のルートパスである C:\Program Files\Docker Toolbox
直下に置いてみる。
(Windows 10 では Program Files 内に直接ファイルを作ることはできないので、℃っか違うところで作って move する)
ファイル名は、まんまDockerfile
(拡張子なし)でたぶんOK。
ファイルの中身は以下のようにしてみた。
#利用するUbuntuのイメージ FROM ubuntu:14.04 #プロキシ設定が必要な場合のみ #ENV https_proxy=XXX #ENV http_proxy=XXX #各種インストール RUN apt-get update #protobuf はあえてインストールしない RUN apt-get install -y sudo autoconf automake libtool curl make g++ unzip pkg-config wget git
Dockerfile をビルド
docker build -t ubuntu1404 .
でビルドする。(-t
はタグ名なので必須だが任意の文字列)
イメージの取得も行うため、結構時間かかる。
追記
しかも、私の環境では powershell の描画更新がバグって
debconf: unable to initialize frontend: Dialog debconf: (TERM is not set, so the dialog frontend is not usable.) debconf: falling back to frontend: Readline debconf: unable to initialize frontend: Readline debconf: (This frontend requires a controlling tty.) debconf: falling back to frontend: Teletype
とか出たりしたけど、気にしないでおこう・・・
さらに追記
さらに私の環境ではビルドが終了すると、上記の描画問題に加え、以下の警告が表示された。
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
うーん、大丈夫なのかなぁ。
内容としては「 '-rwxr-xr-x' になってるよ!」ってだけだから問題なさそうだけど。
イメージの確認
docker images
でイメージが作成されたことを確認する。
PS C:\Program Files\Docker Toolbox> docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu1404 latest 1d8f1efde705 10 minutes ago 382MB
たぶん入ってるっぽい。
コンテナの起動
docker run -it -v /work:/work ubuntu1404
で起動する。(前回行った共有フォルダのマウントも有効にしている)
Dockerfile によるカスタマイズの確認
とりあえず make あたりを実行すしてみる。
root@8c8f74f92f1a:/# make make: *** No targets specified and no makefile found. Stop.
と出て、 make というコマンドを認識してるっぽいので、成功していることがわかる。
とりあえず今回は Dockerfile を使用して、 Ubuntu による protobuf-c のコンパイルの準備までやった。
次回は、protobuf および protobuf-c のコンパイルに焦点を当てて記事を書く。
Docker でホストマシンのストレージ移動と共有フォルダのマウント
Docker ホストマシンのストレージを移動する
イメージを入れる前に、Docker ToolBox を使用している場合は、C:\Users\<ユーザー名>\.docker\machine\machines\<マシン名>
に仮想ディスクファイル (.vmdk) が作られるらしい。
私の環境ではCドライブが切迫しているので、取り急ぎDドライブに移動する。
基本的に↓参照でおk。
(注意:VirtualBox立ち上げっぱなしで.vboxファイル編集してもダメ。.vboxファイルは仮想マシン起動時ではなく、VirtualBox本体を立ち上げるときに読み込まれるらしい。)
データを永続化するために、ストレージを共有フォルダ化する
dockerコンテナは、そのままではデータを永続的に保持できないらしい。そのため、共有フォルダを使用して、データ永続化を実現する必要がある。
ぱっと調べた感じ、参考になるのはあったが、Windows野郎の私にとってはsshの手順とかも慣れていないのですんなりいかなかった。ので、備忘録として手順等を残しておく。
1. VirtualBoxに共有フォルダ設定する
とりあえずここではD:\docker\work
を共有フォルダにしてみた。
2. 起動時設定ファイルを作る
Docker Machineの起動時に、共有フォルダが自動でマウントされるように設定ファイルと作る。
docker-machine ssh
実行- power shell で実行すると文字化けするので、git bash でやった方が良いかも
/var/lib/boot2docker/bootlocal.sh
に以下のように書いて保存する- bash で操作するから、たぶん vi 使わないといけないんだけど、
sudo vi /var/lib/boot2docker/bootlocal.sh
てな感じで sudo が必要
- bash で操作するから、たぶん vi 使わないといけないんだけど、
mkdir -p /d/docker/work mount -t vboxsf -o defaults,iocharset=utf8,uid=1000,gid=50 work /d/docker/work
3. 設定を有効にする
最後にいったんdocker-machine stop default
した後に再度 docker-machine start default
で docker を再起動する。
参考
- Docker toolbox on windows マウント:Dockerコンテナの中でホストのフォルダを見たい - Qiita
- Docker MachineでDドライブなどUsers以外を自動マウントする - Qiita
共有フォルダをマウントしてコンテナを起動する
docker run -it -v /work:/XXX <コンテナ名>:<タグ>
で、上述した work のシンボリックリンクの共有フォルダが、 コンテナ上に XXX フォルダとしてマウントされる。
うーん、ややこしいなぁ。
Docker を Windows 10 Home 環境で動作させてみる
あらすじ
前回
Windowsでのmakeとかがうまくいかなかったので、開き直って「もうLinux環境でやってやる!」となったので、Dockerをインストールすることにする。
Docker ToolBox
どうやらWindows 10 ProじゃないとDocker for Windowsを動かしてくれないそう。(Hyper-Vの関係らしいけど、詳しいことはわからん)
Windows 10 Home民専用に、VirtualBox必須という条件付きでDockerできるDocker ToolBoxというものがあるらしい。民の私はこれをインストールする。
インストール
ググってたら、
こちらがわかりやすそうだったんで、これを参考にする。
起動
とりあえず上記記事を参考に起動するところまでやってみた。
とりあえず現状把握している状況としては、予想だけどこんな感じ。
Oracle VM Virtual Box マネージャー
なるもので、VirtualBox上でどれくらいリソース食っているか確認できる- Dcoker CLIを起動すると、Power Shell が起動する
Dockerで遊ぶ
一通りのチュートリアルが以下にあったのでそちらを参考にいろいろやってみる。
よく使うと思われるDockerコマンド
docker pull <イメージ名>
- イメージ名を取得する
docker images
- 取得済みイメージ一覧を表示
docker run <イメージ名> <コンテナで起動するコマンド>
- 取得済みのイメージをについて、コンテナを作成(create)し、そのコンテナを起動(start)する
- これだけだと、コマンド実行後にすぐにコンテナは終了するが、
docker run -it <イメージ名> <コンテナで起動するコマンド>
のように-it
オプションを付けると、コンテナ接続を終了しない
docker stop <プロセス番号>
- 指定したプロセス番号のコンテナを終了する
- プロセス番号は、
docker ps
で確認できる
コンテナの再操作
docker run -it
でコンテナ起動後、power shell を閉じても、docker stop
しない限り、コンテナは終了しないみたい。
そうなると、power sherll 閉じた後に再びコンテナの操作する必要があると思うが、その場合はdocker attach <プロセス番号>
を使用してコンテナの再操作ができる。
コンテナの終了方法
上記のdocker stop
でもよいが、操作中ならCtrl + d
でも終了できる。
コンテナやイメージの削除方法
下を参照。
基本的に、イメージを削除するためにはまずはコンテナを削除する必要があるっぽい。
で、コンテナは終了していてもID自体は残っているらしい。
とりあえずここまで。
次はubuntuのイメージでも入れてみたいと思います。
Protocol Buffers のC言語版で遊んでみる
ことの成り行き
Windows PC から、C言語しか動作しない低性能ハードウェアとEthernet通信するという案件がある。
もともと、Windows PC からIoT機器に対するEthernet通信(というかMQTT)では伝文のシリアライズフォーマットにJSONの使用を考えていた。しかし、対低性能ハードウェア視線で考えると、C言語でJSONのパースはちょっときついかも・・・
そこで、C言語でも実装できるようなシリアライズフォーマットで何か良いのないかなぁと探していたら、protobuf-c
なるものを見つけた。
protobuf-cとは、google謹製Protocol BuffersのC言語版らしい。
もともと、MQTTに適したシリアライズフォーマットを調査してたときにProtocol Buffersは候補に挙がっていたので、「こんなのもあるのかー」と一応存在自体は把握していた。が、対象がC++やPythonであると思っていたので、「それならお手軽JSONでいいやー」とスルーしていた。
ここにきて、C言語対応のシリアライズフォーマットとして筆頭候補に挙がってきたので、ちょっとどんなものなのか遊んでみる。
実行環境
とりあえず本番環境がWindows10 IoTなので、それに近い環境で手元にあるWindows10 64bitでいろいろやってみる。
環境の構築
Readme.mdに書かれているが、
protobuf-c requires a C compiler, a C++ compiler, protobuf, and pkg-config to be installed.
と書いてあるので、それらを入手する必要がある。
(the autotools (autoconf, automake, libtool) must also be installed
と言われているのでそららもいるかもしれないが、とりあえず今は様子見しとく。なお、Qiitaの記事にautoconf
の説明で参考になるものがあった。)
タチが悪いことに、環境がWindowsなので、色々遠回りに環境構築する必要がある。
備忘録を兼ねて、それらを残しておく。
protobuf-c
のクローン
とりあえず環境作成のためには、protobuf-c
を自前ビルドすることが前提のようなので、このソースコードをgithubからクローンする。
CコンパイラおよびC++コンパイラの入手
手持ちにgit bash
があったのでそれで代用するという手抜きをする。
(git bash
にはもともとgccコンパイラが入っているっぽい)
ちなみに、git bash
はGit for Windowsをインストールする過程で入手できる。
注意
普通にgit bash
を使って、後述するmake
すると、
/usr/bin/sh: line 1: C:/Program: No such file or directory
とかいって怒られる。
これに結構ハマったんだけど、どうやらgit bash
のデフォルトインストール先がC:\Program Files\Git
なのでC:\Program Files\Git\usr\bin\sh.exe
にアクセスしようとする過程で、半角スペースが含まれるのでアクセス不可になってたっぽい。
いろいろ対処法探したんだけど、これといって良いのが見つからなかったので、最終解決手段として私はC:\Program Files\Git
フォルダをC:\Git
(C直下)にコピーして、そのフォルダ内のgit bash
を使用することでmake
を解決できた。
protobuf
の入手(windows)
githubのreleasesページから~win32.zip
をダウンロードする。
binフォルダ内にprotoc.exe
があるので、それを取得。
pkg-config
の入手(windows)
Readme.md#buildingに書いてある通り、./config
を使用できるようにする必要がある。そのため、pkg-config
が必要。
こちらからtar.gzをダウンロードし、そいつを、クローンしたprotobuf-c
フォルダの中に展開する
注意
そのまま./configure
やると
configure: error: Either a previously installed pkg-config or "glib-2.0 >= 2.16" could not be found. Please set GLIB_CFLAGS and GLIB_LIBS to the correct values or pass --with-internal-glib to configure to use the bundled copy.
とか言われてエラーになったので、こちらを拝見して、./configure --with-internal-glib
と実行する。うまくいった。
make
の入手(windows)
素のWindows環境では、make
コマンドが効かないので、それを用意する必要がある。
とりあえずgnuwin32からインストーラをダウンロードする。(Complete package, except sources の SetUp )
git bash
を使用する場合、前述したmake
実行できないトラップがあるので注意。
protoc-c
の生成
./pkg-config/configure --with-internal-glib && make && make install
で行けるやろ!
って思って実行したけど、
/usr/bin/sh: -c: line 0: syntax error near unexpected token `(' /usr/bin/sh: -c: line 0: `test -f config.h || C:/Program Files (x86)/GnuWin32/bin/make stamp-h1' make: *** [config.h] エラー 1
って怒られる。こりゃWindowsは無理かなーってことで今諦めモードです。
こうなったら意地でもどうなるかやってみたいので、Linux環境でやるしかないね。
てことで、秘蔵っ子のDocker for Windowsに手を出してみるか・・・!
備考
なお、autoconf
を使用したautogen.sh
を試してみたいのだが、Windows用autoconfのGnuWin32
が鯖落ち?してるので手に入れることができない・・・
C#でTCP通信のプログラムを作ってみる
主題の通り、作ってみるのだが、とりあえず今は調査中なので「これは押さえておきたい」というところのメモ
目的
基本的にはサーバープログラムを作る。
同時に複数のコネクションが接続されることを想定する。
基本的には↓が参考になる。
ただし、ReadObject
やWriteObject
の拡張メソッドは自前実装しなければならないとのこと。
やらないといけないこと
定期的な死活監視が必要
クライアントは一度コネクションを張ると、切断せず接続しっぱなしにする予定。
そのため、クライアントとの接続が生きているかを監視する必要がある。
解決策
常時コネクション
Windows10が勝手に自動更新してウザイとき
Windows10で自動更新がかかるのを制御する方法。作業中にいきなりCPU100%とかなって邪魔されるので、自動更新を切ります。
Windows10 Pro であることが前提です。あと、更新が一切かからなくなるので、手動更新は自己責任です。
Windows Update を無効にする方法
↓に答えがあります。
一点、Windows Update が再び勝手に開始されることを防ぐためにローカルグループポリシーをいじる必要があるのですが、gpedit.msc
を実行すると、ローカルグループポリシーエディターが起動します。
dotnet ef migrations add したら Unable to create an object of type 'ApplicationDbContext' と怒られるとき
ことの成り行き
もともと dotnet core 1.1 のプロジェクトを dotnet core 2.0 にターゲットフレームワークを差し替えた時のお話。
コードファーストでDBを作るために、主題の通り dotnet ef migrations add XXX
を実行したら Unable to create an object of type 'ApplicationDbContext'
と怒られた。
ググったら既知の問題らしかったので、備忘録として残す。
解決方法
↓に書かれている通り、Program.cs
を修正する。
一応念のため、ソースコードを記載しておく。
public static void Main(string[] args) { // REPLACE THIS: // BuildWebHost(args).Run(); // WITH THIS: var host = BuildWebHost(args); using (var scope = host.Services.CreateScope()) { // Retrieve your DbContext isntance here var dbContext = scope.ServiceProvider.GetService<ApplicationDbContext>(); // place your DB seeding code here DbSeeder.Seed(dbContext); } host.Run(); // ref.: https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/ } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build();
WebHost.CreateDefaultBuilder
なんてねーよって怒られるとき
で、これだけじゃうまくいかないのが嫌なところ。
dotnet core 1.1 のプロジェクトがベースの場合、上記の通り、 WebHost.CreateDefaultBuilder
が存在しないって怒られる。
これは、Nuget しているパッケージのバージョンも dotnet core 2.0 用に更新する必要があるから。
ここまでやって、やっと先に進めた。
けど・・・
結局マイグレーションがうまくいかない。
dotnet ef migrations add XXX
を実行すと、成功したようになるんだけど、DB側にはテーブルが作られていない。
コードファースト諦めるかなぁ。要調査