20200117のdockerに関する記事は11件です。

Docker Hub の Source API ってなんだろう?

微妙に昨日の話(Docker Hub の Build triggers の使い方)に関連した内容になります。Build triggersとは別件で、shields.ioを使ってDockerイメージをAutomated Buildsを使っていることを示すバッジを表示しようと思ったのですが、ここを見ると「Docker Automated build」と「Docker Cloud Automated build」の2つがあって、さてどっちを使うべきなんだろう?と

先に結論を書くと後者の「Docker Cloud Automated build」バッジの方が新しく、最近ビルドしたものであればこちらを使います。2019年1月のInfoQの記事「新しいDocker HubがDocker CloudとDocker Storeを統合」によると、Docker Hubエクスペリエンスリリース時に新しい「自動ビルドプロセス」が提供されており、以前のものは「クラシック自動ビルド」と呼ばれているそうです。つまり古い「Docker Automated build」のバッジはクラシック自動ビルド用だと思います。

古い「Docker Automated build」のバッジを使用すると(新しい)Automated Buildsを使用していてもDocker API(curl https://registry.hub.docker.com/v2/repositories/イメージ名)のレスポンスはis_automatedtrueにはなりません。(参考 Docker build shield show "manual" instead of "automated"?)同様にdocker searchでもAUTOMATEDOKになりません。Docker APIはクラシック自動ビルドの情報を参照しているようです。

では新しい「Docker Cloud Automated build」のバッジはどの情報を参照しているのでしょうか?shields.ioの新しいAutomated Buildsへの対応の修正「feat: [DockerCloud] and automated. 」から https://hub.docker.com/api/build/v1/source/?image=イメージ名 というURLを発見しました。Build triggersと同じAPIのようです。

そこで試しにクエリーパラメータをつけずにGETしてみた所、以下のエラーメッセージが返ってきました。

$ curl -sS https://hub.docker.com/api/build/v1/source/ | jq
{
  "error": "Source API list view needs an image to filter"
}

どうやらこのAPIは Source API と呼ばれているようです。

クエリーパラメータimageを指定した場合のレスポンスは以下のようになります。Automated Buildsの設定が取得できました。この内容はイメージ名さえ分かれば誰でも認証なしに取得できるので秘密情報ではありません。(deploykeyが少し気になりますが、認証なしの場合は常に空になっているようです。)

$ curl -sS https://hub.docker.com/api/build/v1/source/?image=shellspec/openwrt | jq .
{
  "meta": {
    "limit": 25,
    "next": null,
    "offset": 0,
    "previous": null,
    "total_count": 1
  },
  "objects": [
    {
      "autotests": "SOURCE_AND_FORKS",
      "build_in_farm": true,
      "build_settings": [
        "/api/build/v1/setting/8c416bda-1599-430a-bf05-3cee4d58ed78/",
        "/api/build/v1/setting/e4128afa-03dc-44d7-8fa9-80ce78163874/"
      ],
      "channel": "Stable",
      "deploykey": "",
      "image": "shellspec/openwrt",
      "owner": "shellspec",
      "provider": "Github",
      "repo_links": false,
      "repository": "openwrt-docker",
      "resource_uri": "/api/build/v1/source/0312d9d5-8f97-4274-9594-2b3a80b0d3e3/",
      "state": "Success",
      "uuid": "0312d9d5-8f97-4274-9594-2b3a80b0d3e3"
    }
  ]
}

改めて、昨日作成した Build triggers のエンドポイントを見てみると以下のような形式でした。

https://hub.docker.com/api/build/v1/source/0312d9d5-(略)/trigger/a3(秘密)86/call/

つまり最初の0312d9d5-で始まる部分は(プロジェクトを示す)uuidで、秘密情報ではないことがわかります。2番目の(秘密)の部分がTrigger Tokenなのでしょう。

他に Source API にどんなものがあるか、GitHubで探してみましたが、Automated BuildsとBuild triggers以外の使用例は見つかりませんでした。Docker Hubでも正式にドキュメント化はされてないようです。(私が見つけられなかっただけかもしれませんが)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FROM scratchからビルドするDockerイメージをAutomated Buildsにする方法

Docker Hubにある非公式のイメージを使用する場合、それがどうやって作られているか気になりますよね?Automated Buildsであれば、Dockerfileから生成されているので、何をやっているかがわかりますが、直接イメージがpushされている場合、なにが含まれているかわかりません。Automated Buildsなら確実に信用できるというわけではありませんが、ビルド手順を公開し自動的に構築することで利用者の不安を軽減することが出来ます。

Automated Buildsにしていなかった理由

私は基本的にAutomated Buildsにしているのですが、これまでしていなかったのがOpenWrtのDockerイメージのビルドです。私はshellspecというシェルスクリプトのテスティングフレームワークを開発しているのですが、そのテスト環境の一つとしてOpenWrtを使用しています。Docker HubにはOpenWrtが公開しているイメージがあるのですが最新バージョンしかありません。古いバージョンでもテストしたかったので独自でビルドしています。その手順がOpenWrtが公開しているtar.gzをdocker importする方法です。

手元でやるならdocker importで簡単にイメージが作れるのですが、Automated BuildsではDockerfileから生成します。DockerfileのFROMにtar.gzは指定できませんし、ADDにURLを指定した場合、tar.gzは展開されません。(ローカルファイルからtar.gzをADDした場合は展開されます。)そのため今までは手元でビルドしたdockerイメージをpushしていました。

どうやってAutomated Buildsにしたか?

使用した機能はCustom build phase hooksです。Docker HubのAutomated Buildsはbuildやpushの前後等にフックを入れることが出来ます。またビルド処理(docker buildコマンドの実行)そのものを入れ替えることも出来ます。これを利用してビルドの前(hooks/pre_build)でtar.gzファイルをダウンロードして、このファイルをDockerfileでADDしています。

実装

Automated BuildsはGitHubやBitbucketと連携してソースコードをpushしたタイミングで、ソースコードのDockerfileを元にDocker HubがDockerイメージをビルドします。フックスクリプトも同じくソースコードのリポジトリに含めます。今回必要なのはビルド前のフックなので(Dockerfileと同じ階層に)hooks/pre_buildを作成します。

まず先にDockerfileの内容です。

Dockerfile
#IMPORT https://downloads.openwrt.org/releases/19.07.0/targets/x86/64/openwrt-19.07.0-x86-64-generic-rootfs.tar.gz
FROM scratch
ADD imports/openwrt-19.07.0-x86-64-generic-rootfs.tar.gz /
CMD /bin/sh

#IMPORTで始まる行を参照し、そのURLからファイルをダウンロードしてimportsディレクトリに保存するという処理をhooks/pre_buildで行っています。(マルチステージビルドの事も考えて#IMPORTは複数記述できるようにしています。)

hooks/pre_build
#!/bin/sh -eu

while read -r cmd path; do
  [ "$cmd" = "#IMPORT" ] || continue
  curl -vsSfL "$path" -o "imports/${path##*/}"
done < "$DOCKERFILE_PATH"

フックについて

フックではファイルをダウンロードするだけでなくapt-getも使用できたので自由度はかなり高いです。ディストリは現時点ではUbuntu 16.04 xenialが使われていました。フックを利用することで複雑なビルドでもAutomated Buildsにすることができるでしょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VS CodeでDocker開発コンテナを便利に使おう

はじめに

  • ローカル環境で開発し、Linux環境にデプロイしてテストするのが面倒
  • Dockerを使っていい感じに開発環境を作りたい
  • しかし色々設定や構築が面倒

そんな方のためにDockerコンテナを用いた開発環境をVS Codeから便利に構築、運用できる拡張機能「Remote-Containers」の使い方のご紹介です。

この拡張機能の素晴らしさ

VS Codeの拡張機能「Remote-Containers」はコンテナ内でVS Codeを立ち上げ、ホストマシンのVS Codeと通信させることであたかもローカル環境で開発しているような操作感でコンテナ内開発が行えるというものです。

詳しい構成は公式ドキュメントに図があります。


(https://code.visualstudio.com/assets/docs/remote/containers/)

また、複数の開発環境をVS Code上から管理して、ワンクリックでコンテナを立ち上げることが可能です。


(https://code.visualstudio.com/assets/docs/remote/containers/)

そのために開発を始める際にコンテナをコマンドから立ち上げ、シェルをアタッチしてコンテナ内に入るなどの作業が必要なくなります。

ローカル環境でVS Codeを開いて開発を始めるのとほぼ同じ感覚でコンテナ内での開発が始められるのです。

システム要件は以下になります。

  • Windows: Docker Desktop 2.0+ on Windows 10 Pro/Enterprise. (Docker Toolbox is not supported.)
  • macOS: Docker Desktop 2.0+.
  • Linux: Docker CE/EE 18.06+ and Docker Compose 1.21+. (The Ubuntu snap package is not supported.)

環境構築のための環境構築

Docker

まずDockerをインストールしますが、ここは省略します。

筆者はWindows環境にDocker Desktopをインストールしましたが、想像を絶する艱難辛苦を味わいました。

VS Code 拡張機能

VS Code上でctrl + shift + Xで拡張機能メニューを開き、「Remote-Containers」を検索してインストールします。

Microsoft公式なので安心(?)です。

Remote-Containers / Remote-SSH / Remote-WSLをひとつにしたRemote Developmentという拡張機能もあるのでそちらでも大丈夫です。

git

GithubのMicrosoft公式リポジトリに設定ファイルのサンプルがあるので、それをcloneしてくるとスムーズです。

なのでgitをインストールしましょう(手順省略)。

サンプルのリポジトリは以下です。

vscode-remote-try-python

今回はPythonを使いますが、node.jsやjava、goなどもあります。

必要なのは.devcontainerディレクトリ配下のDockerfileとdevcontainer.jsonなので、そこだけ持ってきても構いません。

Remote-Containersの機能で「Try a Sample」というのがあり、cloneしなくてもこれらのリポジトリを使って試すことができますが突然docker imageのビルドが始まるのでやや面喰います。

開発環境構築

プロジェクト構成

例えばPythonのアプリケーションの開発環境を作るとします。

ディレクトリ構成を以下のようにしてVS Codeからprojectディレクトリを開きます。

project/
    └ .devcontainer/
        ├ Dockerfile
        └ devcontainer.json
    └ .git/
    └ package/
        ├ __init__.py
        ├ __main__.py
        └  module.py
    ├ requirements.txt
    └ .gitignore

f1メニューまたは左下に現れる緑色のアイコンをクリックして「Remote-Containers: Open Folder in Container...」を選択します。


(https://code.visualstudio.com/assets/docs/remote/containers/)

するとVS Codeが.devcontainer配下のDockerfileとdevcontainer.jsonを読み込み、その設定に従ってDockerコンテナを立ち上げてくれるという寸法です。

それでは、Dockerfileとdevcontainer.jsonの中身を見て具体的に何が起こっているのかを理解しましょう。

Dockerfile

ここは普通のDockerfileで、特別なことはありませんがユーザー権限回りの設定をいい感じにやってくれています。

#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------

FROM python:3

Docker imageをビルドするための元となるイメージを指定する項目です。

pythonのバージョンを詳しく指定したい場合はここをpython:3.7などにします。

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN apt-get update \
    && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \

    && apt-get -y install git iproute2 procps lsb-release \

    ~~~

    && groupadd --gid $USER_GID $USERNAME \
    && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \

    && apt-get install -y sudo \
    && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
    && chmod 0440 /etc/sudoers.d/$USERNAME \

ここでapt-getの設定とユーザーの権限回りを設定しています。

要はsudoできる権限を持ったvscodeというユーザーでコンテナを扱えるようにしているようです。

devcontainer.json

こちらがこの拡張機能のミソです。

    "name": "Python 3",
    "context": "..",
    "dockerFile": "Dockerfile",

    "settings": { 
        "terminal.integrated.shell.linux": "/bin/bash",
        "python.pythonPath": "/usr/local/bin/python",
        "python.linting.enabled": true,
        "python.linting.pylintEnabled": true,
        "python.linting.pylintPath": "/usr/local/bin/pylint"
    },

    "appPort": [ 9000 ],

    "postCreateCommand": "sudo pip install -r requirements.txt",

    "remoteUser": "vscode",

    "extensions": [
        "ms-python.python"
    ]
}

ここにjson形式で書かれている項目がRemote-Containers拡張機能の設定となります。

  • name
    • Dev Containerの表示名を指定できます(Dockerコンテナ名とは別物です)。
  • context
    • プロジェクトのルートを指定します。
    • この場合devcontainer.jsonがいる.devcontainerディレクトリの一つ上なので".."が指定されています。
  • settings
    • コンテナ側のVS Codeにおける各種設定を行う項目です。シェルやPythonのパスなど。
  • appPort
    • ホストマシンからアクセスできるコンテナのポート番号を指定します。
    • docker runするときの-pオプションで9000:9000と指定するのと同じです。
    • つまりホストマシンのブラウザでlocalhost:9000を叩くとコンテナのlocalhost:9000につながります。
  • postCreateCommand
    • イメージをビルドした後にコンテナ内で実行されるコマンドを書くことができます。
    • この場合はプロジェクトのルートにあるrequirements.txtに書かれたパッケージがインストールされます。
  • extensions
    • コンテナ側のVS Codeにインストールされる拡張機能を指定できます。

公式ドキュメントによると、その他にも色々設定できる項目があります。

デフォルトではプロジェクトのルートディレクトリがコンテナの/workspaceにバインドされますが、

{   
    "workspaceFolder": "/home/vscode",
    "workspaceMount": "type=bind,source=${localWorkspaceFolder},target=/home/vscode/project"
}

のようにすれば、/home/vscodeにバインドされてVS Codeで開くデフォルトのディレクトリもそこになります。

{   
    "containerEnv": {
        "WORKSPACE": "/home/vscode"
    }
}

containerEnv項目を指定すると、コンテナ内で使える環境変数を設定できます。

{   
    "runArgs": [
        "--name=project_dev_container"
    ]
}

runArgsの項目で、コンテナ立ち上げ時のオプションを直接指定することもできます。

実際にはVS Codeがこのdevcontainer.jsonを読み込んで各種オプションをつけてdocker runしてコンテナを立ち上げています。

その際にrunArgsの項目で指定した文字列のリストがスペース区切りで追加されるわけです。

さらに詳しくはこちら : Developing inside a Container - devcontainer.json reference

その他個別設定

git

コンテナにバインドするプロジェクトディレクトリに.git/が入っていると、そのままコンテナ内のVS Codeのバージョン管理機能が使えます。

VS Codeのバージョン管理機能は大変便利で、git addやgit commit、git pushなどがGUIで行えます。

しかしながらコンテナ内でモートリポジトリと通信しようとすると、毎回Githubの認証が必要になってしまいます。

ですがそこは我らがVS Code、gitの認証情報をホストマシンと共有できる機能が付いています。

Developing inside a Container - Sharing Git credentials with your container

まずホストマシンとでGithubのユーザー名やメールアドレスを.gitconfigファイルに保存しておきます。

$ git config --global user.name "Your Name"
$ git config --global user.email "your.email@address"

ユーザールートにある.gitconfigにこれらの設定が書き込まれていますが、これをVS Codeが自動でコンテナにコピーしてくれるようです。

次にパスワードなどの認証情報ですが、二通り設定方法があります。

https通信を使ってidとパスワードで認証している場合、gitのcredential helperにパスワードを保存しておけばその設定がコンテナと同期されます。

Caching your GitHub password in Git

$ git config --global credential.helper wincred

sshでの認証では、ホストマシンでSSH agentにGithub用の公開鍵を登録しておくとその設定が同期されるようです。

PowerShellで

ssh-add $HOME/.ssh/github_rsa

とするとSSH agentに鍵が登録されます。

しかしながらSSH agentが起動していない場合が多く、そのときは管理者権限でPowerShellに入って

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
Get-Service ssh-agent

するか、GUIでサービス > OpenSSH Authentication Agentのプロパティから設定できます。

詳しくはWindows 10のssh-agentをコマンド プロンプト、WSL、Git Bashで使ってみた#ssh-agent-の有効化など。

AWS Access Key

コンテナ内からAWS S3と通信しようとすると、アクセスキーの問題が発生します。

ホストマシンのユーザールートにある.awsディレクトリ内にアクセスキーの情報があり、それをコンテナ内でも読み込みたいものです。

しかしながらgitの場合とは異なりそこは自動的に読み込んではくれないようです。

それゆえに一度コンテナの外からdocker cpを使ってコンテナにコピーしてくる必要があります。

docker cp $HOME/.aws {コンテナ名}:home/vscode

ここで、Remote-Containersで立ち上げるコンテナに名前がついてると便利です。

先ほどのdevcontainer.jsonのrunArgsの項目で、

{   
    "runArgs": [
        "--name=project_dev_container"
    ]
}

のようにしてコンテナ名をつけるようにすると良いでしょう。

素晴らしい航海

実際に使ってみると、普通にVS Codeで開発するのとほぼ同じ感覚で開発コンテナを扱うことができます。

また、Pythonで開発する際には仮想環境を用意するのが普通ですがコンテナ内で環境を構築することでその必要がなくなります。

なぜなら、各プロジェクトごとに違うコンテナを使っているのでパッケージをグローバルにインストールしても環境を汚染しないからです。

そして、Pythonのバージョンごとにイメージが用意されているので本番環境に合わせてそれを指定することもできます。

(この辺りはRemote-Containersというよりdockerを使うことのメリットですが)

こうした開発環境をワンクリックで開いたり、切り替えたりできるわけです。

また、この拡張機能はポートのバインドも自動で行ってくれるため、フロントエンド開発でのローカルサーバーもストレスなく使うことができます。

ただし、例えばnode.jsなどは3000番ポート指定でローカルサーバーが立ち上がるのでそのポートをローカルマシンに公開しなければなりません。

その場合はdevcontainer.jsonで

{   
    "appPort": [ 3000 ]
}

のように設定しておきましょう。

参考

公式ドキュメント、長い

この記事を見てRemote-Containersを使い始めました。感謝!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECSでdocker volumeマウントのownerを指定する

ECSでdocker volumeをマウントするとownerはrootになります。
指定したい場合は、タスク定義のボリューム定義で、dockerVolumeConfiguration.driverOpts を指定しましょう。
例えば、tmpfsとしてボリュームを作成してownerをuid=1000, gid=1000にしたいときは、

  "volumes": [
    {
      "name": "sharedtmp",
      "dockerVolumeConfiguration": {
        "autoprovision": true,
        "scope": "shared",
        "driverOpts": {
          "type": "tmpfs",
          "device": "tmpfs",
          "o": "uid=1000,gid=1000"
        }
      }
    }
  ]

こうすることで ボリューム作成の際に以下のようにオプションをつけて作成してくれます。

$ docker volume create --opt type=tmpfs --opt device=tmpfs --opt o=uid=1000,gid=1000 sharedtmp

ElasticBeanstalkからECSを使う場合も、Dockerrun.aws.jsonに同じように書くだけです。
以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

scratchコンテナの中身を調べてみた件

scratchコンテナってなんだ?

Dockerコンテナで最小限の構成のものらしい。
ただ、Dockerは簡単に言うとchroot環境なので、chroot環境に必要なものは用意されている模様。

とりあえず作ってみる

Dockerfile書いてビルドしてみます。

Dockerfile
FROM scratch
Terminal
$ docker build -t minimum .
Sending build context to Docker daemon  2.329MB
Step 1/1 : FROM scratch
 ---> 
No image was generated. Is your Dockerfile empty?

あ、怒られた。何も変更がないとビルドが出来ないようなのでとりあえず、適当にテキストファイルを突っ込んでみましょう。

Dockerfile
FROM scratch
COPY ./a.txt /a
Terminal
$ docker build -t minimum .
Sending build context to Docker daemon  2.329MB
Step 1/2 : FROM scratch
 ---> 
Step 2/2 : COPY ./a.txt /a
 ---> Using cache
 ---> 7477d58eb207
Successfully built 7477d58eb207
Successfully tagged minimum:latest

今度はうまく行きました。サイズを見ていきましょう。

Terminal
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
minimum             latest              7477d58eb207        9 minutes ago       2B

2Bytesしかないコンテナができました。

ログインできないのでshを入れてみよう

このままだと中に入ることすら出来ないので、shコマンドをつっこみます。
共有ライブラリも入ってないので、一緒に入れましょう。(以下のそれぞれのファイルをカレントディレクトリに突っ込んでいます)

Dockerfile
FROM scratch
COPY ./sh /bin/sh
COPY ./libc.so.6 /lib/libc.so.6
COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
CMD ["/bin/sh"]
Terminal
$ docker build -t minimum .
Sending build context to Docker daemon  2.328MB
Step 1/5 : FROM scratch
 ---> 
Step 2/5 : COPY ./sh /bin/sh
 ---> f35b86f5ab7d
Step 3/5 : COPY ./libc.so.6 /lib/libc.so.6
 ---> 53dd32bd100f
Step 4/5 : COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
 ---> 0459edeb6cb2
Step 5/5 : CMD ["/bin/sh"]
 ---> Running in f309828bb42f
Removing intermediate container f309828bb42f
 ---> 9be0af83812c
Successfully built 9be0af83812c
Successfully tagged minimum:latest

問題なくできました。

Terminal
$ docker run -it --name minimum minimum:latest sh
# 

ちゃんと入れましたね。

ここから、シェルのビルトインコマンドを使って中身を見ていきます。

Terminal(Dockerコンテナ内)
# cd /
# echo *
bin dev etc lib lib64 proc sys
# cd /bin
# echo *
sh
# cd /dev
# echo *
console core fd full mqueue null ptmx pts random shm stderr stdin stdout tty urandom zero
# cd /etc 
# echo *
hostname hosts mtab resolv.conf
# cd /lib
# echo *
libc.so.6
# cd /lib64
# echo *
ld-linux-x86-64.so.2
# cd /proc
# echo *
1 acpi asound buddyinfo bus cgroups cmdline consoles cpuinfo crypto devices diskstats dma driver execdomains
fb filesystems fs interrupts iomem ioports irq kallsyms kcore key-users keys kmsg kpagecgroup kpagecount
kpageflags loadavg locks mdstat meminfo misc modules mounts mtrr net pagetypeinfo partitions sched_debug
schedstat scsi self slabinfo softirqs stat swaps sys sysrq-trigger sysvipc thread-self timer_list tty
uptime version version_signature vmallocinfo vmstat zoneinfo
# cd /sys
# echo *
block bus class dev devices firmware fs hypervisor kernel module power

これで存在するファイルが全て見れました。
注)
/bin /lib /lib64の下のファイルはもともと存在しないものです。(今回自分で追加した)
/proc/1はshのプロセスがあるので、もともと存在しないものです。(shでログインしているのでそのプロセスのためのディレクトリです。)

わーい、これで最小限のshコマンドの使えるコンテナが出来ました。

あれれー、おっかしいぞー

Terminal
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
minimum             latest              9be0af83812c        11 minutes ago      2.32MB
busybox             1.31.1              6d5fcfe5ff17        3 weeks ago         1.22MB

busyboxよりでかい…

Terminal
$ ls -alh libc.so.6 
-rwxr-xr-x 1 tterashima tterashima 2.0M  1月 17 14:18 libc.so.6

glibcデカ…
busyboxは共有ライブラリ一切使っていないので、余分なものない分小さくなるようですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker for Windowsでwebpack-dev-serverのオートリロードが効かない

環境

Ruby on Rails
React
Docker for Windows

問題

Dockerコンテナ上でwebpack-dev-serverを動かしている時に、
Macでは、ホストでのファイルの変更を検知してauto-reloadされるのに、
Windowsではauto-reloadされない。

調査

Docker for Windowsのボリューム機能がうまくいっていないらしい。
それにより、ホスト側で行ったファイルの変更がコンテナ内に通知されず、auto-reloadが機能しない。

対処

WindowsのローカルにPython環境を構築し、以下のライブラリをインストール。

merofeev/docker-windows-volume-watcher

$ docker-volume-watcher コンテナ名 C:\some\directory

Windows上で実行することで、代わりにファイルの変更をコンテナ内に通知してくれる。

参考文献

・Cant get webpack hotreload with create-react-app and docker windows
・File system watch does not work with mounted volumes

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WAS Liberty を日本語ロケールで起動する

いつの間にか、WAS Liberty のお勧めイメージが Universal Base Images (UBI) 8 をベースにしたものに変わっていました。
UBI 8 ベースの WAS Liberty のイメージを日本語ロケールで使用できるようにカスタマイズしてみます。

UBI 8 ベースのイメージがお勧めに

久しぶりに WAS Liberty イメージの official repository を見ていると、UBI 8 ベースのイメージがお勧めになっていました。

以前からの Ubuntu ベースのイメージと UBI ベースのイメージで Docker Hub も分かれているようです。

Ubuntu ベースのイメージに関しては、ロケールを変える方法が Docker Hub に記載されていたのですが、UBI ベースの方には記載がないようです。。。

Ubuntu ベースのイメージのロケール変更方法:引用(文書作成時の内容)
無題.png

日本語ロケールに変える

前回の記事の内容を利用して、UBI ベースの WAS Liberty のイメージを日本語ロケールに変更してみます。
手順は分かっているので、Dockerfile を作ってイメージをビルドします。以下のような Dockerfile にしてみました。USER の切り替えが入るだけで、以前の内容と同じです。

FROM ibmcom/websphere-liberty:19.0.0.12-full-java8-ibmjava-ubi
USER 0
RUN  dnf update -y \
  && dnf install -y glibc-locale-source \
  && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \
  && echo LANG=ja_JP.UTF-8 > /etc/locale.conf \
  && dnf remove -y glibc-locale-source \
  && dnf clean all \
  && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ENV LANG="ja_JP.UTF-8" \
    TZ="Asia/Tokyo"
USER 1001

ビルドします。

C:\liberty-ubi-jp>docker build -t liberty-ubi-jp .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ibmcom/websphere-liberty:19.0.0.12-full-java8-ibmjava-ubi
19.0.0.12-full-java8-ibmjava-ubi: Pulling from ibmcom/websphere-liberty
(省略)
Step 2/5 : USER 0
(省略)
Step 3/5 : RUN  dnf update -y   && dnf install -y glibc-locale-source   && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8   && echo LANG=ja_JP.UTF-8 > /etc/locale.conf   && dnf remove -y glibc-locale-source   && dnf clean all   && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
(省略)
Step 4/5 : ENV LANG="ja_JP.UTF-8"     TZ="Asia/Tokyo"
(省略)
Step 5/5 : USER 1001
(省略)
Successfully built e4171b20ba08
Successfully tagged liberty-ubi-jp:latest
(省略)

起動してみる

ビルドしたイメージを docker run すると、日本語のメッセージが出力され、日本語ロケールに変わっていることが確認できます。

C:\liberty-ubi-jp>docker run --rm -it liberty-ubi-jp

IBM J9 VM バージョン 8.0.6.0 - pxa6480sr6-20191107_01(SR6) (ja_JP) で、defaultServer (WebSphere Application Server 19.0.0.12/wlp-1.0.35.cl191220191120-0300) を起動しています
[AUDIT   ] CWWKE0001I: サーバー defaultServer が起動されました。
(省略)
[AUDIT   ] CWWKF0011I: defaultServer サーバーは、Smarter Planet に対応する準備ができました。defaultServer サーバーは 32.056 秒で始動しました。

当然ですが、元のイメージを起動すると、英語のメッセージが出力されます。

C:\liberty-ubi-jp>docker run --rm -it ibmcom/websphere-liberty:19.0.0.12-full-java8-ibmjava-ubi

Launching defaultServer (WebSphere Application Server 19.0.0.12/wlp-1.0.35.cl191220191120-0300) on IBM J9 VM, version 8.0.6.0 - pxa6480sr6-20191107_01(SR6) (en_US)
[AUDIT   ] CWWKE0001I: The server defaultServer has been launched.
(省略)
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 31.988 seconds.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

release前のbeatorajaをdockerでビルドしたい人へ

この記事で記載しないこと

  • whats beatoraja?
    • java製のBMSプレイヤー。詳細はgoogle行って
  • dockerて何?
    • 他所をあたってください
  • 黒い画面の使い方
    • それを知らない方は多分こっち参照するべきではない
    • 使い方次第でOS吹き飛ばせるので分からない人はこちらを元に頑張ったほうが安全

手順

1.dockerはインストールしておいてください( docker-compose は使いません)
2.リポジトリをcloneしてリポジトリのディレクトリに飛ぶ

# Clone
$ git clone git@github.com:exch-bms2/beatoraja.git
# Move Current Directory
$ cd beatoraja

3.Dockerfileを編集する

本来この手順は必要ではありませんが、2020/01/17現在baseImageの指定が間違っている状態なのでこのまま docker build を叩くと存在しないイメージを参照しているとしてエラーになります。そのため以下のように修正してください。

before

FROM airdock/oracle-jdk:1.8

after

FROM airdock/oraclejdk:1.8

4.Imageをビルドする

$ docker build -t exch-bms2/beatoraja ./

5.ビルドしたイメージを元にコンテナを立ち上げてjarを作る

$ docker run -v `pwd`:/usr/src/app exch-bms2/beatoraja

正常終了すると、 build/ に生成されています

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Minikubeを使ってKubernetesに触れてみた

Minikubeを使ってKubernetesに触れてみたみたので、その備忘録を書いていきます。
Kubernetesはすでに有名で説明記事も多くあるので、説明に関しては省略させてください。

Minikubeとは

Minikubeは小規模なKuberenetes環境をVM上に作成することのできるパッケージです。
Windows,Linux関係なく構築することが可能です。

Minikubeの環境構築

今回はMacOSを利用します。

まずはkubectlをインストールします。
brewを使います。

brew install kubectl

続いてVM環境のために、VirtualBoxをインストールします。
下記からインストール可能です。
https://www.virtualbox.org/

ダウンロードしたらクリックしてインストールしてください。

続いてMinikubeをインストールします。

brew install minikube

これでMinikubeの環境が整いました。

Minikube起動

Minikubeの起動は下記のコマンドで行います。

minikube start

#このコマンドで状態を見ることができます。
$  minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

#kubectlでクラスターの情報も取得できます。
$ kubectl cluster-info
Kubernetes master is running at https://192.168.64.2:8443
KubeDNS is running at https://192.168.64.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

podを使って複数コンテナを起動してみる

yamlで設定事項を書いていきます。

apiVersion: v1
# Kubernetesが作成するObjectのタイプ
kind: Service
metadata:
    name: client-node-port
#サブタイプ
spec:
    type: NodePort
    ports:
        -   port: 3050
        #podのport
            targetPort: 3000
    selector:
        component: web
apiVersion: v1
# Kubernetesが作成するObjectのタイプ
kind: Pod
metadata:
    name: client-pod
    labels:
        component: web
spec:
    containers:
        -   name: client
        #dockerhubにアップロードしてあるイメージ
            image:イメージ名
            ports:
                -   containerPort: 3000

これをもとに様々なKubrenetesにおけるオブジェクトが作成されます。

Podはユーザーが作成し、デプロイ可能なシンプルで最も最小のユニットです。単一のPodはクラスター上で稼働する単一のプロセスを表現します。Pod内では一つ以上のコンテナが起動します。
詳しくは下記をご覧ください。
https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-overview/

Serviceはkube-proxyとPodの間を受け持つKubernetesクラスターのネットワーク部分に関わるオブジェクトです。今回はNodePortを用いります。

kubectlに紐付ける

作成したConfigをkubernetesに紐づけるには、下記のコマンドを叩きます。

kubectl apply -f ファイル名

#確認はこちら
kubectl get services 
kubectl get pods

MinnikubeはVM上で起動しているため、ブラウザで開くためにはVMのIPアドレスを知る必要があります。IPアドレスは下記コマンド取得します。

minikube ip

ここで取得したIPアドレスとnodePortを入れたアドレスへアクセスするとブラウザに反映されます。
http://IPアドレス:nodePort/

以上になります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミングをかじったからには何らかの制作物を作りたい#4 ~Laravel, ページ作成, ルーティング

説明

このエントリーは初心者がとりあえず何かを作りたいと考え、それのみを理由にして記述しているものの4です。そのため、技術的な誤りや勘違いが多分に含まれている可能性があります。ご了承くださいませ。もしよろしければご指摘やご教示を頂けましたら幸いです。

できたもの

https://www.mend0.top

前回のあらすじ

プログラミングをかじったからには何らかの制作物を作りたい#3 ~作り直し編、完成したもの~
https://qiita.com/tatsuki1112/items/5bbffaa9da8f7727f7c5

実際に作成したものはできていて、それがどんなものなのかを説明した。

Laravel編

今回はLaravelでページを作成し、ルーティングなども行いました。
開発環境のMac上にDockerでLaravelを扱えるようにしました。

ページ作成 ~blade~

Laravelではviewにbladeというテンプレートが使用できます。Bladeを使うと、その中にPHPを記載できたり、テンプレートを継承したり、分割して記述したりなどができます。

今回私が作ったものに関して言えば以下のように分割して記述しています。

ページ名 ファイル名
トップ jangkengTop.blade.php
最強の一手を決める inspection.blade.php
👆のモーダル inspectionModal.blade.php
勝敗を決める judge.blade.php
👆のモーダル judgeModal.blade.php
結果一覧 total.blade.php

これらはすべてsrc/resources/views/layouts/下にあるapp.blade.phpを継承して記述しています。そのため、一度app.blade.phpにhead要素などを記述すれば、それを継承したテンプレートではいちいちそれらを記述する必要がなくなります。
ではそれらは如何にして利用すればよいのでしょうか。

@yield @extends @section @include

まず、viewの親を定義するのに使われるのが@yieldです。今回はbody要素内部以外の部分を共通化したかったのでapp.blade.phpを以下のように記述しました(イメージ)。

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>JANGKENG</title>
</head>

<body>
   @yield('content')
</body>

</html>

それから子ビューを記述しますtop, inspection, judge, totalはすべてこのapp.blade.phpを継承しています。

@extends('layouts.app')

@section('content')

<body>
    内容を記述
    @include('modal')
</body>

@endsection

先頭の@extends('layouts.app')で上記親ビューを継承し、@section@endsectionの間の内容が親ビューのcontent部分に入ります。
今回は@include部分にはモーダルを分割して記述しました。
includeとyieldの違いがいまいちよくわからなかったのですが、どうやらincludeは単なる親子関係などがないhtmlを分割するためにあるものと言う感じでしょうか。
https://stackoverflow.com/questions/41916127/whats-the-difference-between-laravels-yield-and-include

確かに今回モーダル部分を分割した際にも、inspectionModal.blade.phpなどには特別な記述はせず、他のviewと同一のディレクトリに置いてあるのみです。

ルーティング

今回作成したものには、トップ、最強の一手、勝敗、合計という4枚のページがあります。これらを遷移させるためにルーティングをします。
Laravelのルーティングsrc/routes/web.phpで記述されます。
特に説明するよりも普通にコードを見ていただいたほうがわかりやすいと思います。

web.php
Route::get('/', function () {
    return view('jangkenTop');
});

Route::get('/inspect', function (){
    return view('inspection');
});

Route::get('/judge', function () {
    return view('judge');
});

Route::get('/total', 'ResultsController@getResults');

Route::post('/inspect', 'ResultsController@setResults');

それぞれにアクセスされたときにそれぞれのviewを返すという形です。total画面のみ、DBが関連してくるので単にviewを返すのではなく、コントローラーを経由しています。
このへんについては後ほど記述します。

今日はこのへんで、次回はLaravelMixやJqueryについて書きます!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Install docker on Ubuntu 18.04

Ubuntu 18.04 で docker インストール時にすること。

要約

  • userns-remapでコンテナ内のrootをホストの非rootにする
  • sudo無しでdockerを使用できるようにする

インストール

% sudo apt install docker.io -y

userns−remapでコンテナのrootをホストの非rootにする

コンテナ内でのUID,GIDをホスト環境と異なるものにマッピングする。

まず、dockremap (dock-remap, not docker-map) ユーザーを追加する。

% sudo useradd dockremap

# コンテナのrootがホストの165536になる。
% cat /etc/subuid
ubuntu:100000:65536
dockremap:165536:65536

% cat /etc/subgid 
ubuntu:100000:65536
dockremap:165536:65536

# docker設定ファイルにuserns-remapを入れる(daemon.jsonは最初存在しない)
# default指定はdockremap指定
% sudo vi /etc/docker/daemon.json 
% cat /etc/docker/daemon.json
{
    "userns-remap": "default"
}

# dockerに反映させるためにリスタート
% sudo service docker restart

# Rootが/var/lib/dockerから変わっていることを確認
% sudo docker info | grep "Docker Root Dir:"
Docker Root Dir: /var/lib/docker/165536.165536
WARNING: No swap limit support

sudo無しでdockerを使用できるようにする

ユーザーをdockerグループへ追加する。

# ユーザー名ubuntuの場合
% sudo usermod -aG docker ubuntu

# ログインしてグループへの追加反映状態に
% su -l ubuntu

# エラーにならないことを確認
% docker version
...
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む