v6プラスとPPPoE(IPv4)の併用
PPPoE(IPv4)の併用
前回の記事のように設定すればPCやスマートフォンからはインターネットに問題なく接続できますが、PS4のボイスチャットが使えなくなりました。フレッツはマルチセッションができるので、もう1台ルーターを使ってPPPoE(IPv4)を使った接続を作成して回避します。
ネットワーク構成は下の図のようにします。中央のWXY-1750DHP2が今回購入したv6プラス対応のルーターで、PCやスマートフォンなどはこれに接続します。そして右のWSR-600DHPは同じくBUFFALOのルーターで、v6プラス利用前まで使っていたものです。これとPS4を接続します。
また、WXR-1750DHP2のLANポートとWSR-600DHPのWANポートをLANケーブルでつなぎます。
WXR-1750DHP2の設定
v6プラス対応ルーターの設定です。「PPPoEパススルー」の「使用する」にチェックします。
また、このルーターのネットワークは仮に192.168.11.0/24とします。
WSR-600DHPの設定
1.「IPアドレス取得方法」で「PPPoEクライアント機能を使用する」を選択する。
2.「PPPoE」で@niftyから送付されたIDとパスワードで接続する設定を作成する。
また、このルーターはネットワークを分けます。ネットワークは仮に192.168.12.0/24とします。
まとめ
これでPS4はv6プラスを使わずにインターネットに接続できるのでボイスチャットも使えるようになりました。インターネット接続の速度はv6プラス利用前と同じ状況になりますが、今のところゲームをしている時に問題は出ていません。また、プロバイダが変わった影響かボイスチャットで相手の音声が途切れ途切れになる問題が解決しました。
v6プラスを使ってインターネット接続速度を改善する
v6プラス利用前に起こっていた問題
家のインターネット回線の速度が夜に数百kbpsと劇的に遅くなり、ニコニコ動画やYoutubeの動画を再生するのに動画時間の何倍も待ったりWebサイトやツイッターの画像の表示も数十秒待つような状況になっていました。業を煮やして調べると、NURO光やv6プラスにすると回線速度の低下がなくなるらしいので対策をすることにしました。
フレッツ光 2017年 急激に遅い評判増える その原因は? | 実際の速度は800M以上! NURO光の実測や評判は?
夜インターネット回線が遅いのを改善してみた(@nifty/フレッツ光/v6プラス/WXR-1900DHP): わかぶろぐ
私は賃貸マンションに住んでいて、インターネット回線はフレッツ光のマンションタイプ(100Mbps)、プロバイダはYahoo! BBでした。NURO光にするには回線を引けるかどうか大家の方と相談が必要だったり時間と手間がかかりそうだったので、自分だけで手続きができるv6プラスを申し込んでみることにしました。
フレッツの回線タイプによってはv6プラスは使えないようですが、自分のマンションが対応しているタイプ(書類によるとNマンション1Bですが、下のサイトのどれに該当するかはよく分かりません。)は対応してました。
サービス内容|フレッツ・v6オプション|フレッツ光公式|NTT東日本|インターネット接続ならフレッツ光
v6プラスについて
フレッツのIPv4は契約者数が多い上に装置で最大200Mbpsに制限されていて通信量が多くなる夜に速度低下が起こるようで、それがv6プラスで回避できるようです。
【v6プラス】無料オプションで爆速に!「遅い」「重い」を解決するおすすめのネット回線(プロバイダ)&ルーター - 踊るびあほりっく
https://www.jpne.co.jp/service/v6plus/
また、v6プラスにすると固定IPアドレスを使えなくなったり特定のポートを使う通信ができなくなるので自宅サーバーや特定ポートを使う一部のゲームに影響があるようです。とは言え1契約でIPv4のセッションも同時に張ることができるので、v6プラスを使っても大丈夫だと思います。私はPS4はIPv4を使ってインターネットに接続できるようにしました。
プロバイダとの契約
v6プラスに対応しているプロバイダはいくつかありますが私は@niftyにしました。v6プラスオプションは無料で利用できます。
7/10に申し込んで7/12には書類が郵送されてきました。ただ、よく分からないのは7/12にはルーターの設定をしてIPv4が使えるようになったと思ってたんですが、@niftyの課金開始日が8/1でした。もしかしたらルーターにYahoo! BBの設定が残っていてインターネットに接続できていたのかもしれません。
8/3に「IPv6接続オプション」の申し込みが完了したというメールが来て、v6プラスが使えるようになりました。
v6プラス対応のルーターの準備
v6プラスを使うには対応するルーターが必要です。v6プラス対応のホームゲートウェイ(ひかり電話対応ルーター)か、市販のv6プラス対応ルーターを用意する必要があります。私はホームゲートウェイを使っていなかったので、BUFFALOのWXR-1750DHP2というルーターを購入しました。
BUFFALOのv6プラス対応ルーターはサイトに一覧があります。
IPv6接続動作確認済みサービス/機器一覧 | バッファロー
ルーターの設定
v6プラスを使ってインターネットに接続するようにルーターの設定をします。ブラウザでルーターの設定画面にログインした後、
1.「IPアドレス取得方法」で「インターネット@スタートを行う」を選択する。
2.PPPoEの設定がもしあれば削除する。
3.「IPv6接続方法」で「NDプロキシを使用する」を選択する。
当初は1と2だけ行っていましたが深夜0:30頃に回線が数分間切断されるという現象が発生していました。対策として3の設定を行うと解決します。
※2017/8/28追記:当初は3で「IPv6パススルーを使用する」を選択していましたが、セキュリティ上危険だと指摘を頂いたので「NDプロキシを使用する」を選択するように変更しました。
ルーターの設定ができたらv6プラスがちゃんと使えるか下のサイトで確認します。
「v6プラスのインターネットアクセス(v6プラス用)」の試験でOKが表示されていれば成功です。
感想
v6プラスにする前は速くて20Mbps程度、夜は最悪1Mbpsを下回る状況でしたが、v6プラスを使い始めたら夜でも60Mbps以上出るようになり最初に書いた問題も解決しました。最大100Mbpsの回線契約でこれだけ速度が出るのは驚きです。
また、これくらい速度が出るとYoutubeで4K解像度・60FPSの動画も、ページを表示してすぐに再生を開始しても止まることなく視聴できます。
プロバイダを変更する手間とルーターの購入が必要でしたが、快適にインターネットを使えるようになったので満足してます。
Dockerのビルドのレスポンスを整形して出力する
F#でDockerイメージをビルドする - locabloではレスポンスをそのまま出力していたのでパースして出力できるようにしました。
F#っぽいコードにならなかったのが残念...
let formatResponse line = let root = JObject.Parse(line) let hasProp key = root.Properties() |> Seq.map (fun x -> x.Name) |> Seq.contains key let valueOf (key : string) = string root.[key] let newLine = System.Environment.NewLine let builder = new System.Text.StringBuilder() if hasProp "id" then builder.AppendFormat("{0}: ", valueOf "id") |> ignore if hasProp "progress" then builder.AppendFormat("{0} {1}{2}", valueOf "status", valueOf "progress", newLine) |> ignore elif hasProp "stream" then builder.AppendFormat("{0}", valueOf "stream") |> ignore elif hasProp "status" then builder.AppendFormat("{0}{1}", valueOf "status", newLine) |> ignore else builder.Append(line) |> ignore builder.ToString() let outputBuildResponse (responseStream : Stream) : unit = seq { use reader = new StreamReader(responseStream, Text.Encoding.UTF8) while not reader.EndOfStream do yield reader.ReadLine() } |> Seq.map formatResponse |> Seq.iter (printf "%s")
前回の記事の出力がこれで、
{"stream":"Step 1/2 : FROM busybox\n"} {"status":"Pulling from library/busybox","id":"latest"} {"status":"Pulling fs layer","progressDetail":{},"id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":16384,"total":699311},"progress":"[=\u003e ] 16.38 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":260087,"total":699311},"progress":"[==================\u003e ] 260.1 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":424839,"total":699311},"progress":"[==============================\u003e ] 424.8 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":490375,"total":699311},"progress":"[===================================\u003e ] 490.4 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":539527,"total":699311},"progress":"[======================================\u003e ] 539.5 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":621447,"total":699311},"progress":"[============================================\u003e ] 621.4 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Verifying Checksum","progressDetail":{},"id":"1cae461a1479"} {"status":"Download complete","progressDetail":{},"id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":32768,"total":699311},"progress":"[==\u003e ] 32.77 kB/699.3 kB","id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Pull complete","progressDetail":{},"id":"1cae461a1479"} {"status":"Digest: sha256:c79345819a6882c31b41bc771d9a94fc52872fa651b36771fbe0c8461d7ee558"} {"status":"Status: Downloaded newer image for busybox:latest"} {"stream":" ---\u003e c75bebcdd211\n"} {"stream":"Step 2/2 : RUN ls\n"} {"stream":" ---\u003e Running in 74350655bd58\n"} {"stream":"bin\ndev\netc\nhome\nproc\nroot\nsys\ntmp\nusr\nvar\n"} {"stream":" ---\u003e 7fc898365619\n"} {"stream":"Removing intermediate container 74350655bd58\n"} {"stream":"Successfully built 7fc898365619\n"}
formatResponse関数を使ってパースして出力するとこうなります。
Step 1/2 : FROM busybox latest: Pulling from library/busybox 1cae461a1479: Pulling fs layer 1cae461a1479: Downloading [=> ] 15.93 kB/699.3 kB 1cae461a1479: Downloading [===============> ] 211.8 kB/699.3 kB 1cae461a1479: Downloading [=======================> ] 326.5 kB/699.3 kB 1cae461a1479: Downloading [=========================> ] 359.3 kB/699.3 kB 1cae461a1479: Downloading [============================> ] 392.1 kB/699.3 kB 1cae461a1479: Downloading [==============================> ] 424.8 kB/699.3 kB 1cae461a1479: Downloading [=================================> ] 474 kB/699.3 kB 1cae461a1479: Downloading [=====================================> ] 523.1 kB/699.3 kB 1cae461a1479: Downloading [========================================> ] 572.3 kB/699.3 kB 1cae461a1479: Downloading [============================================> ] 621.4 kB/699.3 kB 1cae461a1479: Downloading [==============================================> ] 654.2 kB/699.3 kB 1cae461a1479: Downloading [=================================================> ] 687 kB/699.3 kB 1cae461a1479: Downloading [==================================================>] 699.3 kB/699.3 kB 1cae461a1479: Verifying Checksum 1cae461a1479: Download complete 1cae461a1479: Extracting [==> ] 32.77 kB/699.3 kB 1cae461a1479: Extracting [=======================================> ] 557.1 kB/699.3 kB 1cae461a1479: Extracting [==================================================>] 699.3 kB/699.3 kB 1cae461a1479: Extracting [==================================================>] 699.3 kB/699.3 kB 1cae461a1479: Pull complete Digest: sha256:c79345819a6882c31b41bc771d9a94fc52872fa651b36771fbe0c8461d7ee558 Status: Downloaded newer image for busybox:latest ---> c75bebcdd211 Step 2/2 : RUN ls ---> Running in 5c8584208f21 bin dev etc home proc root sys tmp usr var ---> b95a8e54a8f1 Removing intermediate container 5c8584208f21 Successfully built b95a8e54a8f1
F#でDockerイメージをビルドする
概要
DockerにはDocker Engine APIがあり、HTTPを使ってアクセスできます。
Docker Engine API v1.39 Reference
また、各言語向けにSDKがあります。
Develop with Docker Engine SDKs and API | Docker Documentation
今回はDocker for Windowsを使ってF#からDockerイメージのビルドを実行します。
環境は次の通りです。
- Windows 10 Pro (1703)
- Docker for Windows (Version 17.03.1-ce-win12 (12058), Channel: stable)
- F# 4.1
- Visual Studio Community 2017
Docker for Windowsの設定
Docker for WindowsをインストールしてDockerが使えるようになったら、ローカルのDocker EngineにアクセスするためにTLSを無効にします。有効な状態で使うこともできると思いますが今回はそこまで調べられてませんので、無効にした状態でアクセスします。
やり方は、まずタスクトレイのDockerアイコンを右クリックして(なければまずはDockerを起動します)、"Settings..."をクリックします。
ウィンドウが開いたら、左のエリアで"General"を選び、右側のエリアの"Expose daemon on tcp://localhost:2375 without TLS"のチェックを外します。
Dockerイメージのビルド
Docker.DotNet
.NET向けのSDKとしてDocker.DotNetがあるのでこれを使います。
GitHub - Microsoft/Docker.DotNet: .NET (C#) Client Library for Docker API
ただし、記事作成時点でNuGetで公開されているバージョン(2.124.3)にはまだDockerイメージをビルドするAPIは含まれていません。GithubのmasterブランチにはAPIが存在するので、自分でライブラリをビルドして使います。
ビルドは簡単で、Visual Studioで開いて"Docker.DotNet"というプロジェクトをビルドするだけです。他のプロジェクトは今回は使いません。
ビルド後、自分のプロジェクトの参照に、
を追加します。
コード
DockerイメージのビルドをするF#のコードです。
let buildDockerImage (tar : byte[]) : Stream = use client = (new DockerClientConfiguration(new Uri("http://localhost:2375"))).CreateClient() use dockerfileTarStream = new MemoryStream(tar) let imageBuildParams = new ImageBuildParameters() imageBuildParams.Tags <- new List<string>() imageBuildParams.Tags.Add("build-test") client.Images.BuildImageFromDockerfileAsync(dockerfileTarStream, imageBuildParams) |> Async.AwaitTask |> Async.RunSynchronously let outputBuildResponse (responseStream : Stream) : unit = seq { use reader = new StreamReader(responseStream, Text.Encoding.UTF8) while not reader.EndOfStream do yield reader.ReadLine() } |> Seq.iter (printfn "%s")
buildDockerImage関数はdockerのコマンドだと
docker build -t build-test .
と同じことをします。
buildDockerImage関数ではまずDockerClientオブジェクトを作成します。
use client = (new DockerClientConfiguration(new Uri("http://localhost:2375"))).CreateClient()
作成するときのURIには上の"Docker for Windowsの設定"でチェックをつけたところに書かれていた"http://localhost:2375"を指定します。
次にビルドパラメータ(ImageBuildParameters)のオブジェクトを作成します。
let imageBuildParams = new ImageBuildParameters() imageBuildParams.Tags <- new List<string>() imageBuildParams.Tags.Add("build-test")
imageBuildParams.Tagsにイメージ名である"build-test"を指定します。これは、"docker build"コマンドの"-t"オプションに指定する値に該当します。
最後にDocker Engine APIにDockerイメージのビルドをリクエストします。
client.Images.BuildImageFromDockerfileAsync(dockerfileTarStream, imageBuildParams) |> Async.AwaitTask |> Async.RunSynchronously
1番目の引数はDockerfileをTARデータを持つSystem.Streamオブジェクトで、この後でデータの作成方法を説明します。2番目の引数はビルドパラメータです。
buildDockerImage関数を実行してリクエストに成功するとHTTPレスポンスのデータを読み取れるStreamオブジェクトが返ります。
outputBuildResponse関数はbuildDockerImage関数で返すHTTPレスポンスのStreamオブジェクトを読み込んで標準出力に出力する関数です。F#のシーケンスとyieldを使って1行受信するごとに出力します。
TARデータの作成
Docker Engine API(Engine API v1.24 | Docker Documentation)の"BUILD IMAGE FROM A DOCKERFILE"の項目を読むと、リクエスト例が
POST /v1.24/build HTTP/1.1 {{ TAR STREAM }}
となっています。先ほどのbuildDockerImage関数の引数"tar"にTARフォーマットのデータを表すバイト配列を渡すと、Docker.DotNetのBuildImageFromDockerfileAsync()の第一引数に渡されてこのHTTPリクエストのボディになります。
SharpZipLib
TARデータを作るのに今回はSharpZipLibというライブラリを使います。バージョンは0.86.0です。
これはNuGetでプロジェクトに追加します。
コード
Dockerfileを読み込んでTARデータを作る関数のコードです。
/// "dockerfileDirPath"はDockerfileがあるディレクトリのパス。 let createDockerfileTar (dockerfileDirPath : string) : byte[] = let generateTar (outputStream : Stream) : unit = use archive = TarArchive.CreateOutputTarArchive(outputStream) let dockerFileEntry = TarEntry.CreateEntryFromFile("Dockerfile") archive.WriteEntry(dockerFileEntry, false) let currentDirectory = Directory.GetCurrentDirectory() try use memoryStream = new MemoryStream() Directory.SetCurrentDirectory(dockerfileDirPath) generateTar memoryStream memoryStream.ToArray() finally Directory.SetCurrentDirectory(currentDirectory)
createDockerfileTar関数はDockerfileを読み込んでTARデータを作成、バイト配列にして返します。
内部のgenerateTar関数でDockerfileを読み込んでTARデータを作っています。TarArchiveやTarEntryがSharpZipLibで定義されている型で、
use archive = TarArchive.CreateOutputTarArchive(outputStream)
で引数に渡されたStreamオブジェクトにデータを書き込むようなアーカイブオブジェクトを作り、
let dockerFileEntry = TarEntry.CreateEntryFromFile("Dockerfile") archive.WriteEntry(dockerFileEntry, false)
でDockerfileをTARに追加しています。
archiveはDisposeメソッドが呼ばれないとデータの書き込みが行われないようなので、関数にして関数終了時にデータがStreamオブジェクト(outputStream)に書き込まれるようにしています。
また、カレントディレクトリをDockerfileがあるディレクトリにしないとDocker Engine APIにリクエストを投げた時に失敗する(理由はわかりませんが)ので、TARデータの作成前後でカレントディレクトリを変更しています。
実行
アプリケーション全体のコードです。
open Docker.DotNet open Docker.DotNet.Models open ICSharpCode.SharpZipLib.Tar open System open System.Collections.Generic open System.IO let createDockerfileTar (dockerfileDirPath : string) : byte[] = let generateTar (outputStream : Stream) : unit = use archive = TarArchive.CreateOutputTarArchive(outputStream) let dockerFileEntry = TarEntry.CreateEntryFromFile("Dockerfile") archive.WriteEntry(dockerFileEntry, false) let currentDirectory = Directory.GetCurrentDirectory() try use memoryStream = new MemoryStream() Directory.SetCurrentDirectory(dockerfileDirPath) generateTar memoryStream memoryStream.ToArray() finally Directory.SetCurrentDirectory(currentDirectory) let buildDockerImage (tar : byte[]) : Stream = use client = (new DockerClientConfiguration(new Uri("http://localhost:2375"))).CreateClient() use dockerfileTarStream = new MemoryStream(tar) let imageBuildParams = new ImageBuildParameters() imageBuildParams.Tags <- new List<string>() imageBuildParams.Tags.Add("build-test") client.Images.BuildImageFromDockerfileAsync(dockerfileTarStream, imageBuildParams) |> Async.AwaitTask |> Async.RunSynchronously let outputBuildResponse (responseStream : Stream) : unit = seq { use reader = new StreamReader(responseStream, Text.Encoding.UTF8) while not reader.EndOfStream do yield reader.ReadLine() } |> Seq.iter (printfn "%s") [<EntryPoint>] let main argv = let dockerfilePath = argv.[0] let dockerfileDir = Directory.GetParent(dockerfilePath).FullName createDockerfileTar dockerfileDir |> buildDockerImage |> outputBuildResponse 0
main関数はコマンドライン引数でDockerfileのパスを受け取って親ディレクトリのパスを取得しています。その後、TARデータ作成→Dockerイメージのビルドリクエストの送信→レスポンスの出力、という処理をしています。
また、次のような内容のDockerfileを作って保存し、
FROM busybox RUN ls
先ほどのアプリケーションの引数にDockerfileのパスを指定して実行すると次のように出力されてDockerイメージがビルドされます。
> .\DockerBuild.exe ..\..\..\Dockerfile {"stream":"Step 1/2 : FROM busybox\n"} {"status":"Pulling from library/busybox","id":"latest"} {"status":"Pulling fs layer","progressDetail":{},"id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":16384,"total":699311},"progress":"[=\u003e ] 16.38 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":260087,"total":699311},"progress":"[==================\u003e ] 260.1 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":424839,"total":699311},"progress":"[==============================\u003e ] 424.8 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":490375,"total":699311},"progress":"[===================================\u003e ] 490.4 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":539527,"total":699311},"progress":"[======================================\u003e ] 539.5 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":621447,"total":699311},"progress":"[============================================\u003e ] 621.4 kB/699.3 kB","id":"1cae461a1479"} {"status":"Downloading","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Verifying Checksum","progressDetail":{},"id":"1cae461a1479"} {"status":"Download complete","progressDetail":{},"id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":32768,"total":699311},"progress":"[==\u003e ] 32.77 kB/699.3 kB","id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Extracting","progressDetail":{"current":699311,"total":699311},"progress":"[==================================================\u003e] 699.3 kB/699.3 kB","id":"1cae461a1479"} {"status":"Pull complete","progressDetail":{},"id":"1cae461a1479"} {"status":"Digest: sha256:c79345819a6882c31b41bc771d9a94fc52872fa651b36771fbe0c8461d7ee558"} {"status":"Status: Downloaded newer image for busybox:latest"} {"stream":" ---\u003e c75bebcdd211\n"} {"stream":"Step 2/2 : RUN ls\n"} {"stream":" ---\u003e Running in 74350655bd58\n"} {"stream":"bin\ndev\netc\nhome\nproc\nroot\nsys\ntmp\nusr\nvar\n"} {"stream":" ---\u003e 7fc898365619\n"} {"stream":"Removing intermediate container 74350655bd58\n"} {"stream":"Successfully built 7fc898365619\n"} > docker images REPOSITORY TAG IMAGE ID CREATED SIZE build-test latest 68c39e9a6aa8 37 seconds ago 1.11 MB busybox latest c75bebcdd211 3 weeks ago 1.11 MB
HTTPレスポンスの出力の1行1行はJSONで、Dockerビルド中に中で標準出力に出力された文字列が返ってきます。標準出力の内容なので中に改行コード("\n")が含まれています。また、">"が"\u003e"にエスケープされています。
2017/06/13追記:レスポンスを整形して出力できるようにしました。
Azure Container RegistryへDockerイメージを登録する
Dockerのイメージを登録・管理できるAzure Container Registryを使ってみたので手順をまとめます。
流れは次の通りです。
- Docker for Windowsをインストールする
- Azure Container Registryでレジストリを作成する
- WindowsでDockerイメージを作成する
- Container Registryへ作成したDockerイメージを登録する
PCはWindows 10 Pro (64bit)です。
※注意:記事作成時点ではAzure Conteiner Registryに登録したDockerイメージを削除できないようです。
Docker for Windowsのインストール
Docker for WindowsはHyper-Vを使うのでWindows 10(64bit)のProfessionalエディションなどが必要(https://docs.docker.com/docker-for-windows/install/#what-to-know-before-you-install)ですが、Docker Toolbox(https://docs.docker.com/toolbox/overview/)を使えばその他WindowsでもDockerを使えるようです。
インストールはDocker公式ページのドキュメントに従って行います。
Install Docker for Windows | Docker Documentation
Docker for WindowsにはStableチャンネルやEdgeチャンネルがあるようですが、今回はStableチャンネルのインストーラーをダウンロードしてインストールしました。
インストーラーの指示に従ってインストールをした後、Hyper-Vが無効の状態の場合はDockerを起動するとダイアログが表示されるようです。
ダイアログに書かれているようにHyper-Vを有効にするとVirtualBoxが使えなくなります。それで問題なければOKボタンをクリックするとHyper-Vが有効になりPCが再起動します。
再起動したらdockerコマンドが使えるか確認します。
コマンドプロンプトやPowershellを開いて次のコマンドを実行します。
> docker --version
Docker version 17.03.1-ce, build c6d412e
> docker-compose --version
docker-compose version 1.11.2, build f963d76f
> docker-machine --version
docker-machine.exe version 0.10.0, build 76ed2a6
またはVisual Studio Codeで端末ウィンドウを開いても確認できます。
各コマンドでバージョンが表示されればOKです。
コンテナーレジストリの作成
Azure Container Registryのドキュメントの手順に沿って作成します。
プライベート Docker レジストリの作成 - Azure Portal | Microsoft Docs
- Azure Portalを開く
- Marketplaceで「Azure コンテナー レジストリ」を検索する
- 発行元がMicrosoftの[Azure コンテナー レジストリ」を選択する
- [作成]をクリックする
- コンテナーレジストリ名などを入力して[作成]をクリックする
レジストリ名には英数字しか使えないようです。
また、ここで管理ユーザーを有効にするとdockerコマンドでContainer Registryへログインする時に、ユーザー名にレジストリ名を、パスワードにアクセスキーを使えるようになります。今回はPCで作成したイメージをdockerコマンドでContainer Registryに登録したいので有効にします。
Dockerイメージの作成
Dockerイメージを作成するにはDockerfileが必要ですが、MonoをインストールしたUbuntuのコンテナを作成するDockerfileが既にあるのでそれを例に使います。Dockerfileの内容は次の通り。
FROM ubuntu:xenial-20161010
RUN apt-get update
RUN apt-get install -y mono-complete
任意のフォルダにこのDockerfileを保存します。
次はコマンドプロンプトまたはPowershellを開き、Dockerfileを保存したフォルダに移動後、Dockerイメージをビルドします。
> cd [Dockerfileのあるフォルダ]
> docker build -t [レジストリ名].azurecr.io/mono .
[レジストリ名]はContainer Registryを作成したときに指定した名前です。"-t"オプションの値は一定のフォーマットでなければなりません(次の章で説明します)。また、最後に" .“(ピリオドの前に空白あり)があります。
ビルドが終わったらイメージが作成できているか確認します。
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[レジストリ名].azurecr.io/mono latest a5c78a372b93 6 hours ago 747 MB
Container RegistryへのDockerイメージの登録
Dockerイメージのリポジトリ名のフォーマット
Dockerイメージのリポジトリ名は次のフォーマットになっている必要があります。
[レジストリ名].azurecr.io/[Dockerイメージ名]
[Dockerイメージ名]は名前空間付きDockerイメージの名前です。名前空間はDockerイメージが属するグループのことで、"/“で区切って複数レベルの階層を構成できます。詳しくは次のドキュメントの[主な概念]のリポジトリとイメージを参照してください。
Azure のプライベート Docker コンテナー レジストリ | Microsoft Docs
“docker build"の時の”-t"オプションに指定した値はこのフォーマットになっています。
もし上記のフォーマットになっていなかったり、名前を変えたい場合はdockerコマンドで変更できます。
> docker tag [現在のリポジトリ名] [新しいリポジトリ名]
Container Registryへの登録
Container RegistryへのDockerイメージの登録は次のドキュメントを参考にします。
Docker イメージをプライベート Azure レジストリにプッシュする | Microsoft Docs
まずはdockerコマンドでContainer Registryへログインします。
> docker login [レジストリ名].azurecr.io/ -u [ユーザー名] -p [パスワード]
Login Succeeded
上記ドキュメントではAzure Active DirectoryのサービスプリンシパルというもののIDとパスワードを使っていますが、Container Registry作成時に管理ユーザーを有効にしているので別途ユーザーとパスワードが作成されています。そのユーザーとパスワードは、
- Azure Portalを開く
- 作成したContainer Registoryを選択
- [アクセスキー]をクリックする
で確認できます。
ログイン後、Container RegistryへDockerイメージをプッシュします。
> docker push [レジストリ名].azurecr.io/mono
The push refers to a repository [[レジストリ名].azurecr.io/mono]
...
latest: digest: sha256:6e9a312338c88dcfb10fede48e5f0ff0d423ff15ed387510842d2945cd3633c9 size: 1782
プッシュが終わったら、
と操作してプッシュしたDockerイメージが表示されるか確認します。
リポジトリ一覧に"mono"があれば登録ができています。