20190323のdockerに関する記事は9件です。

【小ネタ】docker環境を掃除するコマンド

はじめに

Dockerを普通に使っていると、停止状態のコンテナやdanglingなイメージ(REPOSITORYやTAGが<none>になっているもの)がたまっていきます。
これらを一括削除する方法をまとめてみました。

実行コマンド

不要なリソースすべて削除する (docker system prune)

何も考えずに、使われていないと思われるリソースを削除します。ローカルの開発環境であればこれが一番簡単です。

docker system prune | Docker Documentation
https://docs.docker.com/engine/reference/commandline/system_prune/

$ docker system prune
WARNING! This will remove:
        - all stopped containers
        - all networks not used by at least one container
        - all dangling images
        - all dangling build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
d75069ae85738508edbbcb7027d0caff3174ac09629089462f7bdcafd0a56223
b342fa0ac8d3d5e75e403ad77940045a71e221865cb866f46140d1633249d6ba

Total reclaimed space: 8.402MB

Docker imageで不要なものを削除する (docker image prune)

どのコンテナからも参照されておらず、且つdanglingなイメージを削除します。

docker image prune | Docker Documentation
https://docs.docker.com/engine/reference/commandline/image_prune/

$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

docker image pruneがなかった時代は、以下のようにコマンドを組み合わせていましたが、今となっては不要でしょう。
xargsの代わりに、シェルのコマンド置換(「$()」若しくはバッククォート「``」)を組み合わせたパターンもよく見ました。

$ docker images --filter "dangling=true" -q | xargs docker rmi

$ docker rmi `docker images --fileter "dangling=true" -q`

$ docker rmi $(docker images --fileter "dangling=true" -q)

停止状態のDocker containerをすべて削除する (docker container prune)

停止状態のコンテナ(STATUSがExitedかDeadのもの?)をすべて削除します。

docker container prune | Docker Documentation
https://docs.docker.com/engine/reference/commandline/container_prune/

Description
Remove all stopped containers

「stoppped」の定義が見つからなかったのですが、コマンドの挙動からおそらくSTATUSがExitedとDeadのコンテナが対象になるのではと思います。

$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
ba802702150e13e1b95d4868b1eabee1c929d37b38da548786b6f4872be056b4
3dbd0f7d84f6d918473e6e90b971af3bf1b0eb2ce3e524a5db1f00061517859f

Total reclaimed space: 4.201MB

docker container pruneがなかった時代は、以下のようなコマンドがよく使われていたと思います。
これも、xargsの代わりにシェルのコマンド置換(「$()」若しくはバッククォート「``」)を組み合わせたバリエーションがあります。

$ docker ps -q -a| xargs docker rm

$ docker rm `docker ps -q -a`

$ docker rm $(docker ps -q -a)

「-a」オプションをつけると、停止状態のコンテナも実行中のコンテナもすべて出力され、docker rmコマンドの対象となります。
実行中のコンテナを削除しようとしてもエラーになるので、結果として停止状態のコンテナのみが削除される、という動きになります。

補足:docker image/docker containerに関するコマンドの詳細

最近のdockerコマンドは、第一引数に「container」や「image」、「network」などを指定して実行できるように整理されており、何を対象とした操作なのかわかりやすくなっています。
「docker ps」や「docker container ls」は実質的に同じことを実行します。
しかしながら、公式ドキュメントは古いほうのコマンドの説明しか詳細に書いていなかったりするので、探すときには注意が必要です。

Docker image lsの詳細

「docker images」に詳細が記載してあります。

docker images | Docker Documentation
https://docs.docker.com/engine/reference/commandline/images/

Docker container lsの詳細

「docker ps」に詳細が記載してあります。

docker ps | Docker Documentation
https://docs.docker.com/engine/reference/commandline/ps/

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

数学科がDockerの理解度チェックとしてJupyterLabの環境構築

背景

Dockerをとりあえず勉強したけど
では、何か環境を構築できるのか?
つまり、理解に繋がっているのか?の確認

対象読者

  • 初めてDockerで環境構築してみたい人
  • Linuxにそもそも疎い人(ggrksの完全独学野郎)
  • Macユーザー

完成品について

GitHubにあります。

kz-jpylb
    ├── Dockerfile
    ├── work
    ├── README.md
    └── docker-compose.yml

使い方について

はじめに、Gitを使えるようにしておいてください。

例えば、
このリポをforkしてから
Clone with HTTPSってところをおして
出てきたやつをコピーする

$ cd Desktop
$ git clone ここにコピーしたやつ

です。これでDesktopにディレクトリができたと思うので

env.example
UID=下の方で取得方法が観れるのでそれをここに

.env.example.envにrenameしてから

$ docker-compose up -d 

でOKです

docker-composeで困ったこと

docker-compose.ymlを記述の際に次の点がわからなかった。
一応、その他のところも簡単にコメントを書く

docker-compose.yml
version: "3"  #  docker-composeのバージョン、俺の時の最新は3
services:
  jupyterlab: # サービス名
    build:   # imageを直接とってもいいけどDockerfileを別で用意してるからいらない
              # pipで何か追加したいときはDockerfileにかこう
      context: .  # Dockerfileがあるところ
    user: root ########### ← これよ, このuser ###########
    ports:
      - "8888:8888" # ホスト:コンテナ
    volumes:
      - "./work:/home/jovyan/work" ########### ← これよ, この/home/jovyan/work ###########
    environment:
      NB_UID: $UID ########### ← これよ, このUID ###########
      GRANT_SUDO: "yes" ########### ← これよ, このSUDO ###########
    command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし、これですぐ使える

まずUIDについては

を参考にすると

| ユーザーのユーザーID(uid)やグループID(gid)を調べるには、idコマンドを使用する。以下の例では、ユーザーIDが500、グループIDが501であることが分かる。また、所属グループが501となっていることから、ユーザー名と同じ名前のグループ名であることも分かる。 |

$ whoami
unkoman
$ id unkoman
uid=500(nori) gid=501(nori) 所属グループ=501(nori)

次にGRANT_SUDOについては

を参考にすると

GRANT_SUDO=yesは
ユーザー権限なしにjupyterを利用できるするようにするオプションです。

よくわからないけど他の人もみんなこうしてるから俺もこうしよう
できれば解説をコメントでお願いします ?‍♂️

次にvolumeのmountについては

公式の

を参考にすると

docker run --rm -p 10000:8888 -e JUPYTER_ENABLE_LAB=yes -v "$PWD":/home/jovyan/work jupyter/datascience-notebook:9b06df75e445

Example 3: This command pulls the jupyter/datascience-notebook image tagged 9b06df75e445 from Docker Hub if it is not already present on the local host. It then starts an ephemeral container running a Jupyter Notebook server and exposes the server on host port 10000. The command mounts the current working directory on the host as /home/jovyan/work in the container. The server logs appear in the terminal. Visiting http://:10000/?token= in a browser loads JupyterLab, where hostname is the name of the computer running docker and token is the secret token printed in the console. Docker destroys the container after notebook server exit, but any files written to ~/work in the container remain intact on the host.:

と書いてあるのでコンテナ側はどうやら/home/jovyan/workらしい

最後にuser: rootについては

を参考にすると

エラーとかの回避のためにとりあえずつけてる感じ?
できれば解説をコメントでお願いします ?‍♂️

Dockerfileについて

これも簡単にコメント

FROM jupyter/datascience-notebook

MAINTAINER kiwamizamurai # 名前<mail address>  が慣習のよう

RUN pip install jupyterlab
RUN jupyter serverextension enable --py jupyterlab

ベースイメージに何が入っていんかの確認方法がわからんかったし
何を追加でpip installすればいいかわからんかった

パスワード設定について(読み飛ばして良い)(設定したい人向け)

上では
command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし
としたが
command: start.sh jupyter lab
とすれば後からパスワードが設定できる

上のリンクによると

$ docker-compose build
$ docker-compose up

でコンテナ起動させるとパスワード入力画面が現れて、入力しログインする、
その後、JupyterLab上で下記を実行して

from IPython.lib import passwd
passwd()

SHA1の文字列が得られるのでこの文字列を起動時に渡すようにする、つまり

docker-compose.yml
version: "3"
services:
  jupyterlab: 
    build: 
      context: .
    user: root 
    ports:
      - "8888:8888" 
    volumes:
      - "./work:/home/jovyan/work"
    environment:
      NB_UID: $UID 
      GRANT_SUDO: "yes"
    command: start.sh jupyter lab --NotebookApp.token='ここに貼り付ける'

で、

# foregroundで起動していた場合  (-d なし)

ターミナルの画面で  Ctr + C  をしてから
$ docker-compose up -d

ここら辺は

を参考にどうぞ

おっけー

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

数学科が独学でDockerの理解度チェックとしてJupyterLabの環境構築

背景

Dockerをとりあえず勉強したけど
では、何か環境を構築できるのか?
つまり、理解に繋がっているのか?の確認

対象読者

  • 初めてDockerで環境構築してみたい人
  • Linuxにそもそも疎い人(ggrksの完全独学野郎)
  • Macユーザー

完成品について

GitHubにあります。

kz-jpylb
    ├── Dockerfile
    ├── work
    ├── README.md
    └── docker-compose.yml

使い方について

はじめに、Gitを使えるようにしておいてください。

例えば、
このリポをforkしてから
Clone with HTTPSってところをおして
出てきたやつをコピーする

$ cd Desktop
$ git clone ここにコピーしたやつ

です。これでDesktopにディレクトリができたと思うので

env.example
UID=下の方で取得方法が観れるのでそれをここに

.env.example.envにrenameしてから

$ docker-compose up -d 

でOKです

docker-composeで困ったこと

docker-compose.ymlを記述の際に次の点がわからなかった。
一応、その他のところも簡単にコメントを書く

docker-compose.yml
version: "3"  #  docker-composeのバージョン、俺の時の最新は3
services:
  jupyterlab: # サービス名
    build:   # imageを直接とってもいいけどDockerfileを別で用意してるからいらない
              # pipで何か追加したいときはDockerfileにかこう
      context: .  # Dockerfileがあるところ
    user: root ########### ← これよ, このuser ###########
    ports:
      - "8888:8888" # ホスト:コンテナ
    volumes:
      - "./work:/home/jovyan/work" ########### ← これよ, この/home/jovyan/work ###########
    environment:
      NB_UID: $UID ########### ← これよ, このUID ###########
      GRANT_SUDO: "yes" ########### ← これよ, このSUDO ###########
    command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし、これですぐ使える

まずUIDについては

を参考にすると

| ユーザーのユーザーID(uid)やグループID(gid)を調べるには、idコマンドを使用する。以下の例では、ユーザーIDが500、グループIDが501であることが分かる。また、所属グループが501となっていることから、ユーザー名と同じ名前のグループ名であることも分かる。 |

$ whoami
unkoman
$ id unkoman
uid=500(nori) gid=501(nori) 所属グループ=501(nori)

次にGRANT_SUDOについては

を参考にすると

GRANT_SUDO=yesは
ユーザー権限なしにjupyterを利用できるするようにするオプションです。

よくわからないけど他の人もみんなこうしてるから俺もこうしよう
できれば解説をコメントでお願いします ?‍♂️

次にvolumeのmountについては

公式の

を参考にすると

docker run --rm -p 10000:8888 -e JUPYTER_ENABLE_LAB=yes -v "$PWD":/home/jovyan/work jupyter/datascience-notebook:9b06df75e445

Example 3: This command pulls the jupyter/datascience-notebook image tagged 9b06df75e445 from Docker Hub if it is not already present on the local host. It then starts an ephemeral container running a Jupyter Notebook server and exposes the server on host port 10000. The command mounts the current working directory on the host as /home/jovyan/work in the container. The server logs appear in the terminal. Visiting http://:10000/?token= in a browser loads JupyterLab, where hostname is the name of the computer running docker and token is the secret token printed in the console. Docker destroys the container after notebook server exit, but any files written to ~/work in the container remain intact on the host.:

と書いてあるのでコンテナ側はどうやら/home/jovyan/workらしい

最後にuser: rootについては

を参考にすると

エラーとかの回避のためにとりあえずつけてる感じ?
できれば解説をコメントでお願いします ?‍♂️

Dockerfileについて

これも簡単にコメント

FROM jupyter/datascience-notebook

MAINTAINER kiwamizamurai # 名前<mail address>  が慣習のよう

RUN pip install jupyterlab
RUN jupyter serverextension enable --py jupyterlab

ベースイメージに何が入っていんかの確認方法がわからんかったし
何を追加でpip installすればいいかわからんかった

パスワード設定について(読み飛ばして良い)(設定したい人向け)

上では
command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし
としたが
command: start.sh jupyter lab
とすれば後からパスワードが設定できる

上のリンクによると

$ docker-compose build
$ docker-compose up

でコンテナ起動させるとパスワード入力画面が現れて、入力しログインする、
その後、JupyterLab上で下記を実行して

from IPython.lib import passwd
passwd()

SHA1の文字列が得られるのでこの文字列を起動時に渡すようにする、つまり

docker-compose.yml
version: "3"
services:
  jupyterlab: 
    build: 
      context: .
    user: root 
    ports:
      - "8888:8888" 
    volumes:
      - "./work:/home/jovyan/work"
    environment:
      NB_UID: $UID 
      GRANT_SUDO: "yes"
    command: start.sh jupyter lab --NotebookApp.token='ここに貼り付ける'

で、

# foregroundで起動していた場合  (-d なし)

ターミナルの画面で  Ctr + C  をしてから
$ docker-compose up -d

ここら辺は

を参考にどうぞ

おっけー

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

素人がDockerの理解度チェックとしてJupyterLabの環境構築

背景

Dockerをとりあえず勉強したけど
では、何か環境を構築できるのか?
つまり、理解に繋がっているのか?の確認

対象読者

  • 初めてDockerで環境構築してみたい人
  • Linuxにそもそも疎い人(ggrksの完全独学野郎)
  • Macユーザー

完成品について

GitHubにあります。

kz-jpylb
    ├── Dockerfile
    ├── work
    ├── README.md
    └── docker-compose.yml

使い方について

はじめに、Gitを使えるようにしておいてください。

例えば、
このリポをforkしてから
Clone with HTTPSってところをおして
出てきたやつをコピーする

$ cd Desktop
$ git clone ここにコピーしたやつ

です。これでDesktopにディレクトリができたと思うので

env.example
UID=下の方で取得方法が観れるのでそれをここに

.env.example.envにrenameしてから

$ docker-compose up -d 

でOKです

docker-composeで困ったこと

docker-compose.ymlを記述の際に次の点がわからなかった。
一応、その他のところも簡単にコメントを書く

docker-compose.yml
version: "3"  #  docker-composeのバージョン、俺の時の最新は3
services:
  jupyterlab: # サービス名
    build:   # imageを直接とってもいいけどDockerfileを別で用意してるからいらない
              # pipで何か追加したいときはDockerfileにかこう
      context: .  # Dockerfileがあるところ
    user: root ########### ← これよ, このuser ###########
    ports:
      - "8888:8888" # ホスト:コンテナ
    volumes:
      - "./work:/home/jovyan/work" ########### ← これよ, この/home/jovyan/work ###########
    environment:
      NB_UID: $UID ########### ← これよ, このUID ###########
      GRANT_SUDO: "yes" ########### ← これよ, このSUDO ###########
    command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし、これですぐ使える

まずUIDについては

を参考にすると

| ユーザーのユーザーID(uid)やグループID(gid)を調べるには、idコマンドを使用する。以下の例では、ユーザーIDが500、グループIDが501であることが分かる。また、所属グループが501となっていることから、ユーザー名と同じ名前のグループ名であることも分かる。 |

$ whoami
unkoman
$ id unkoman
uid=500(nori) gid=501(nori) 所属グループ=501(nori)

次にGRANT_SUDOについては

を参考にすると

GRANT_SUDO=yesは
ユーザー権限なしにjupyterを利用できるするようにするオプションです。

よくわからないけど他の人もみんなこうしてるから俺もこうしよう
できれば解説をコメントでお願いします ?‍♂️

次にvolumeのmountについては

公式の

を参考にすると

docker run --rm -p 10000:8888 -e JUPYTER_ENABLE_LAB=yes -v "$PWD":/home/jovyan/work jupyter/datascience-notebook:9b06df75e445

Example 3: This command pulls the jupyter/datascience-notebook image tagged 9b06df75e445 from Docker Hub if it is not already present on the local host. It then starts an ephemeral container running a Jupyter Notebook server and exposes the server on host port 10000. The command mounts the current working directory on the host as /home/jovyan/work in the container. The server logs appear in the terminal. Visiting http://:10000/?token= in a browser loads JupyterLab, where hostname is the name of the computer running docker and token is the secret token printed in the console. Docker destroys the container after notebook server exit, but any files written to ~/work in the container remain intact on the host.:

と書いてあるのでコンテナ側はどうやら/home/jovyan/workらしい

最後にuser: rootについては

を参考にすると

エラーとかの回避のためにとりあえずつけてる感じ?
できれば解説をコメントでお願いします ?‍♂️

Dockerfileについて

これも簡単にコメント

FROM jupyter/datascience-notebook

MAINTAINER kiwamizamurai # 名前<mail address>  が慣習のよう

RUN pip install jupyterlab
RUN jupyter serverextension enable --py jupyterlab

ベースイメージに何が入っていんかの確認方法がわからんかったし
何を追加でpip installすればいいかわからんかった

パスワード設定について(読み飛ばして良い)(設定したい人向け)

上では
command: start.sh jupyter lab --NotebookApp.token=''  # passwordなし
としたが
command: start.sh jupyter lab
とすれば後からパスワードが設定できる

上のリンクによると

$ docker-compose build
$ docker-compose up

でコンテナ起動させるとパスワード入力画面が現れて、入力しログインする、
その後、JupyterLab上で下記を実行して

from IPython.lib import passwd
passwd()

SHA1の文字列が得られるのでこの文字列を起動時に渡すようにする、つまり

docker-compose.yml
version: "3"
services:
  jupyterlab: 
    build: 
      context: .
    user: root 
    ports:
      - "8888:8888" 
    volumes:
      - "./work:/home/jovyan/work"
    environment:
      NB_UID: $UID 
      GRANT_SUDO: "yes"
    command: start.sh jupyter lab --NotebookApp.token='ここに貼り付ける'

で、

# foregroundで起動していた場合  (-d なし)

ターミナルの画面で  Ctr + C  をしてから
$ docker-compose up -d

ここら辺は

を参考にどうぞ

おっけー

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

systemdとdockerを組み合わせるときに気をつけること

topic

  • dockerの標準出力の行方
  • docker logging driverでfluentdを利用する場合

systemdとfluentdとdockerを利用した際に、標準出力の扱いに関して詰まったことがあったので下記に記載しておく。

dockerの標準出力の行方

コンテナでアプリを立ち上げたときに大体の人はdocker logsコマンドでコンテナの標準出力を見ると思う。
(アプリの設定で固定ファイルにログをすべて出力する設定等をしている場合は別だが、log4j2などを使っている場合)

systemdからコンテナを立ち上げた際に、docker logsコマンドで表示される内容がすべてsyslogにも出力されているのをみて、えぇ!!と驚いたのでまとめておく。

コンテナの標準出力=プロセスの標準出力

当たり前の話だが、コンテナの標準出力=プロセスの標準出力なのでコンテナをsystemdで起動した場合コンテナの標準出力はsystemdによって拾われる。
そのため、systemdの設定で標準出力関連の設定をデフォルトにしている場合systemdで管理しているプロセスの標準出力(エラー出力を含む)はsystemd→journalログに拾われるため、結果的に/var/log/messages等のログにも同時出力される。

勘違いした理由としては、docker logsコマンドの説明で、docker logging driverをデフォルトのjsonにしている場合は、コンテナIDごとに指定のファイルパスに標準出力のログファイルが蓄積してて、そこを見てるんだよ。
という旨の記載を見た気がして、じゃあプロセスとしての標準出力としては出なくてどっかで出力がうばわれてるんだなーと勝手に解釈してしまった(馬鹿)ためだ。

よって、ログをjournalに拾われたくない場合はsystemdで下記の設定を行う必要がある。

StandardOutput=null

上記は標準出力のみで標準エラー出力に関しては、以前の通りjournalに出力されるので、必要であればエラー出力に関する設定も同様に存在するのでそちらもいじると良い。

そのまま、出力させるのであれば上記の設定は不要。

logging driverでfluentdを指定した場合に標準出力の行方

dockerの公式ドキュメントにも書いてあるが、docker logging driverでjson以外を設定した場合は、docker logsコマンドを利用することができない。

このため、ほほぉjson以外を設定するとコンテナの標準出力は吸い取られるのか!!(馬鹿)と勘違いしていた。
実際、logging driverをfluentdにしたあとはdocker logsコマンドが使えないので標準出力なくなったのかなーとか考えてたときにjournalログにも同じログが出てる!と気がついて、なんでこっちにもでてるのか散々悩んだ。

結局、logging driverをどんな設定にしてもプロセスの標準出力自体はなくならないのでsystemd(upstart)等で管理する場合は通常と同じようにプロセスの標準出力の扱いに関する注意が必要と言うことである。(当たり前)

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

同一リポジトリでLaradock + Nuxt(SSRモード)の環境構築

前提

Docker version 18.09.2
docker-compose version 1.23.2
npm 6.9.0

参考サイト
laradock と nuxt で開発環境構築
Laravel+Nuxt.js
LaravelとNuxt.jsを同一レポジトリで管理するときの構成
Laravel に Nuxt.js プロジェクトを入れたい

Laradockの構築

Laradockをインストール用のディレクトリの作成

mkdir guild-test-environment

Laradockのプロジェクトをクローンする

cd guild-test-environment/
git clone https://github.com/Laradock/laradock.git

作成したディレクトリに移動

cd laradock/

.envファイルを作成する

cp env-example .env

docker-compose.ymlを編集し、Nuxt用のポートをマッピングする

ports:
        - "${WORKSPACE_SSH_PORT}:22"
        - "3000:3000"

.envファイル開発環境の構築をするのでルートディレクトリではなく以下のように変更を行う。

- DATA_PATH_HOST=~/.laradock/data
+ DATA_PATH_HOST=.laradock/data

Dockerコンテナを立ち上げる

docker-compose up -d nginx mysql workspace

指定のDockerコンテナが立ち上がる

Creating volume "laradock_mosquitto" with local driver
Recreating laradock_mysql_1            ... done
Recreating laradock_docker-in-docker_1 ... done
Recreating laradock_workspace_1        ... done
Recreating laradock_php-fpm_1          ... done
Recreating laradock_nginx_1            ... done

workspaceコンテナ内に入る

docker-compose exec workspace bash

※ ちなみにコンテナから抜けるには、Ctrl + P + Q

laravel プロジェクト作成

workspaceに入ったままlaravelプロジェクトをインストール

composer create-project --prefer-dist laravel/laravel {プロジェクト名}

インストール結構時間かかる。。。

.envファイルを編集する

#before
# APP_CODE_PATH_HOST=../
#after
APP_CODE_PATH_HOST=../{プロジェクト名}

(option)
#before
#MYSQL_DATABASE=default
#MYSQL_USER=default
#MYSQL_PASSWORD=secret
#after
MYSQL_DATABASE=hogehoge
MYSQL_USER=develop
MYSQL_PASSWORD=develop

dockerを立ち上げ直す

docker-compose up -d nginx mysql workspace

立ち上がって、laradockフォルダと同じ階層にLaravelプロジェクト名のディレクトリができていたらOK!!

TODO
php artisan maigrationの実行を入れる

Nuxtのインストール

LINK

Nuxt公式で展開してるtemplateにする
LaravelProjectの直下のclientディレクトリに配置

npx create-nuxt-app guild-test/client

初期設定で色々聞かれるのでとりあえず下記で設定

? Project name client
? Project description My ace Nuxt.js project
? Use a custom server framework none
? Choose features to install Linter / Formatter, Prettier, Axios
? Use a custom UI framework buefy
? Use a custom test framework jest
? Choose rendering mode Universal
? Author name 
? Choose a package manager npm

package.json と nuxt.config.jsの編集

package.json

laravel プロジェクトを作成した際に作られた package.json は捨てて、
nuxt の方と入れ替える。

$ rm package.json # laravelインストール時に生成された方を削除
$ mv ./client/package.json package.json #nuxtの方と入れ替える

nuxt.config.js

$ mv ./client/nuxt.config.js nuxt.config.js

内容編集

module.exports = {
  ~ 省略 ~
  build: {
    ~ 省略 ~
  },
  srcDir: './client',    <- nuxt プロジェクトディレクトリパス
  watchers: {                     <- nuxt コマンドでホットリロードを有効にするため
    webpack: {
      poll: true
    }
  }
}

パッケージをnpmでインストール

npm install

完了後にpackge.jsonの編集を行う
なぜ必要なのかは要調査

{
  "name": "guild-test-nuxt",
  ~ 省略 ~
  "scripts": {
    "dev": "nuxt",                                                  <- before
    "dev": "HOST=0.0.0.0 PORT=3000 nuxt",     <- after
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate"
  },
  ~ 省略 ~
}

開発者モードで起動

npm run dev
> client@1.0.0 dev /var/www/guild-test
> HOST=0.0.0.0 PORT=3000 nuxt

ℹ Preparing project for development                                                                                                                  13:37:38
ℹ Initial build may take a while                                                                                                                     13:37:38
✔ Builder initialized                                                                                                                                13:37:38
✔ Nuxt files generated                                                                                                                               13:37:38

✔ Client
  Compiled successfully in 17.35s

✔ Server
  Compiled successfully in 15.14s

ℹ Waiting for file changes                                                                                                                           13:38:05

   ╭─────────────────────────────────────────────╮
   │                                             │
   │   Nuxt.js v2.4.5                            │
   │   Running in development mode (universal)   │
   │   Memory usage: 157 MB (RSS: 295 MB)        │
   │                                             │
   │   Listening on: http://172.31.0.2:3000      │
   │                                             │
   ╰─────────────────────────────────────────────╯

LaravelのAPIからHellowoaldを取得する

client/pages/index.vue

<template>
  <div>{{ data }}</div>
</template>
<script>
export default {
  async asyncData({ app }) {
    const data = await app.$axios.$get('/api')
    return { data }
  }
}
</script>

routes/api.php

//APIテスト用
Route::get('/', function(){ return 'helloworld';});

プロキシモジュールを追加

npm i @nuxtjs/proxy

/nuxt.config.js

module.exports = {
  modules: [
    '@nuxtjs/proxy'
  ],
  /*
   ** Axios module configuration
   */
  axios: {
    // See https://github.com/nuxt-community/axios-module#options
    baseURL: '/'
  },
  proxy:{
    '/api' : "http://localhost:8000"
  }
}

workspaceコンテナ内でNuxt/Laravelサーバを立ち上げる

npm run dev
php artisan serve

画面にhelloworldが出てるはず

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

Java コンテナ化ツール「Jib」はどのくらい Docker のベストプラクティスを満たしているのか

はじめに

Java アプリケーションをコンテナ化するツールに jib があります。

GitHub の README には、Docker のベストプラクティスを知らなくても最適な Docker イメージを作ってくれると書かれています。

Jib builds optimized Docker and OCI images for your Java applications without a Docker daemon - and without deep mastery of Docker best-practices.

そんな Jib がどのくらい Docker イメージのベストプラクティスを満たしているのか調査してみました。

準備

検証には、Spring Initializr で作成した Maven プロジェクトを使います。

jib-maven-plugin の README の通り、pom.xml に以下の記述を追加します。

<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>jib-maven-plugin</artifactId>
  <version>1.0.2</version>
  <configuration>
    <to>
      <image>myimage</image>
    </to>
  </configuration>
</plugin>

ビルドしてみます。

$ ./mvnw compile jib:dockerBuild
    :
    :
    :
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  18.444 s
[INFO] Finished at: 2019-03-23T13:59:31+09:00
[INFO] ------------------------------------------------------------------------

Docker イメージを確認すると ...

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myimage             latest              8ef0bcee6c5d        49 years ago        141MB

Dockerfile を一切書かず、イメージができました !

起動も通常通り成功しました。

$ docker run --rm myimage

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-03-23 05:01:06.902  INFO 1 --- [           main] s.SpringDockerExampleApplication         : Starting SpringDockerExampleApplication on 072b9539cd19 with PID 1 (/app/classes started by root in /)
    :
    :
    :

ここまでハマる点は一切なく、想像以上に簡単でした。

ベストプラクティスへの対応の調査

コンテナイメージをビルドするには、7 best practices for building containers のようなベストプラクティスがあります。

今回は、Jib で作成したイメージが以下のプラクティスを満たしているのか調査します。

  • PID 1 で起動
  • ビルドキャッシュの最適化
  • 不要なツールの削除
  • イメージの最小化
  • レイヤー数の削減
  • 一般ユーザで実行

PID 1 で起動

コンテナ停止時はコンテナ内の PID 1 のプロセスにシグナルが送られるため、PID 1 でアプリケーションを起動することが推奨されています。

Spring Boot 起動時のログを見ると ...

2019-03-23 05:01:06.902  INFO 1 --- [           main] s.SpringDockerExampleApplication         : Starting SpringDockerExampleApplication on 072b9539cd19 with PID 1 (/app/classes started by root in /)

Starting SpringDockerExampleApplication on 072b9539cd19 with PID 1 と出力されており、PID 1 で起動していることが分かります。

ビルドキャッシュの最適化

Jib の README にビルドキャッシュの最適化を目指していることが書かれています。

Fast - Deploy your changes fast. Jib separates your application into multiple layers, splitting dependencies from classes. Now you don’t have to wait for Docker to rebuild your entire Java application - just deploy the layers that changed.

詳細は調べていませんが、これを自作の Dockerfile で再現するには、ある程度 Docker の知識が必要になってきそうです。

不要なツールの削除

コンテナには何が入っているのか調べるため docker exec で sh を実行しようとすると、以下のようにエラーとなりました。

$ docker exec -it $(docker container ls | grep myimage | awk '{print $1}') sh
OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown

FAQ の where is bash によると ...

By default, Jib uses distroless/java as the base image. Distroless images contain only runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution. Check out the distroless project for more information about distroless images.

If you would like to include a shell for debugging, set the base image to gcr.io/distroless/java:debug instead. The shell will be located at /busybox/sh. Note that :debug images are not recommended for production use.

実行に必要な依存関係しか入っておらず、デバッグ用にシェルがほしいならベースイメージを変更するようにとのことです。
ここまで不要なツールを削除した Java のイメージを自作するのは結構大変だと思います。

ちなみに、Java についても、java コマンドは入っていましたが、javac コマンドは入っていませんでした。

$ docker run --rm --entrypoint java myimage -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
$ docker run --rm --entrypoint javac myimage -version
docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"javac\": executable file not found in $PATH": unknown.
~/Documents/src/os1ma/spring-docker-example (master) $

イメージの最小化

イメージサイズを自作の Dockerfile からビルドした場合と比較します。

Dockerfile は以下の通りです。1

FROM openjdk:8u181-jre-alpine3.8

RUN addgroup -S -g 1000 app \
    && adduser -D -H -S -G app -u 1000 app
USER app
WORKDIR /app

COPY target/*.jar .

# *.jar を展開するために sh -c を実行し、
# さらに PID 1 で java プロセスを起動するため exec を使用
CMD ["sh", "-c", "exec java -jar *.jar"]

JAR と Docker イメージをビルドします。

$ ./mvnw clean package
$ docker build -t myimage-openjdk .

イメージサイズを比較すると ...

$ docker image ls
REPOSITORY          TAG                   IMAGE ID            CREATED             SIZE
myimage-openjdk     latest                262fd5db197f        9 seconds ago       99.8MB
myimage             latest                8ef0bcee6c5d        49 years ago        141MB

openjdk:8u181-jre-alpine3.8 をベースに自作した方が小さくなりました。

とはいえ、Alpine ベースで提供されていない2 Amazon Correto を利用した場合よりは小さくなっています。

REPOSITORY          TAG                   IMAGE ID            CREATED             SIZE
myimage-amazon     latest                dd6500aa12d0        4 minutes ago       542MB

なお、Amazon Correto を使った場合の Dockerfile は以下です。

FROM amazoncorretto:8u202

RUN groupadd -r -g 1000 app \
    && useradd -M -r -g app -u 1000 app
USER app
WORKDIR /app

COPY target/*.jar .

# *.jar を展開するために sh -c を実行し、
# さらに PID 1 で java プロセスを起動するため exec を使用
CMD ["sh", "-c", "exec java -jar *.jar"]

レイヤー数の削減

Jib で作成したイメージと Dockerfile から作成したイメージのレイヤ数を比較すると ...

$ docker image inspect myimage | jq '.[0].RootFS.Layers'
[
  "sha256:44873b569cf340a616026da244ebee1bbd7d3f2bb7a0dbf7a6526c4416dea61a",
  "sha256:87c747af6dc3478b57493f1f3a2e0821696f8d56b86b1fef1128d1d74881cf7c",
  "sha256:6189abe095d53c1c9f2bfc8f50128ee876b9a5d10f9eda1564e5f5357d6ffe61",
  "sha256:cdfa1ce6eb7e772884aeab7a2560bee6988f7bba47addeedb636842d72a23702",
  "sha256:5e1ddec1ac755324b4489ba4030512f5f461ace13be7f9617982b0a12dcaec16",
  "sha256:edb7e86863542fc9cfaee3eb48af4678560b396dd5dcc18ee89e089aee23abf4",
  "sha256:769f5c896c76f8bf79881949a0d55cbd768405580f1ae87b4519b16da83d2387"
]
$ docker image inspect myimage-openjdk | jq '.[0].RootFS.Layers'
[
  "sha256:7bff100f35cb359a368537bb07829b055fe8e0b1cb01085a3a628ae9c187c7b8",
  "sha256:dbc783c89851d29114fb01fd509a84363e2040134e45181354051058494d2453",
  "sha256:178e89c683ce4b8f572eb7d89c48a70e39f740b2c81274a58092e02a764732d6",
  "sha256:9f4e44fd5bdc31d8dbe3074d8db6b5ccc13504f65cc3e3bfac580f2f1710840b",
  "sha256:f5892329ace5f98e26db46cf436780fa28747a95303a2e283a9ae41be0246551",
  "sha256:426afce096026f233072c74b991ceec088b7278166096d364bf4db9f214cb238"
]

自作した方が 1 つレイヤーが少なくなっています。
Jib ではビルド時にレイヤキャッシュを利用していることが関係しているのかもしれません。

一般ユーザで実行

コンテナ内で root ユーザを使わないよう、Dockerfile で一般ユーザを作成するというプラクティスがあります。

しかし、Jib で作成したイメージを起動した際のログには (/app/classes started by root in /) と書かれており、root ユーザで実行されていました。

2019-03-23 05:01:06.902  INFO 1 --- [           main] s.SpringDockerExampleApplication         : Starting SpringDockerExampleApplication on 072b9539cd19 with PID 1 (/app/classes started by root in /)

一般ユーザで起動するイメージを作成するには、pom.xml に追記が必要でした。

<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>jib-maven-plugin</artifactId>
  <version>1.0.2</version>
  <configuration>
    <to>
      <image>myimage</image>
    </to>
    <container>
      <user>1000:1000</user>
    </container>
  </configuration>
</plugin>

これで起動してみると ...

$ ./mvnw compile jib:dockerBuild
$ docker run --rm myimage

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-03-23 06:24:42.445  INFO 1 --- [           main] s.SpringDockerExampleApplication         : Starting SpringDockerExampleApplication on c864fdbdb6a7 with PID 1 (/app/classes started by ? in /)

(/app/classes started by ? in /) と表示されており、たしかに root ユーザでなくなりました。

ちなみに、コンテナのユーザは以下のように起動時に設定することも可能です。

$ docker run --rm -u 1000:1000 myimage

まとめ

Jib のセットアップは非常に簡単で、たしかに結構良いイメージを作ってくれました。

また、Jib はコンテナレジストリへのプッシュや Slaffold との連携も可能とのことなので、CI / CD の中で使うと面白そうです。

Java を Native バイナリとして動かす Quarkus にも対応してくれると嬉しいです。


  1. マルチステージビルドでは .m2 のキャッシュが効かずビルドに時間がかかるため、マルチステージビルドは使っていません。マルチステージビルドで .m2 のキャッシュを利用する方法は「Buildkitを使ってMulti-stage BuildでMavenのキャッシュを効かせる」の通りです。 

  2. Image using alpine #1 

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

GitPitchをローカルでプレビューできるdocker imageを作った

どうも、うじまるです
皆さんGitPitch使ってますか? 僕はつい最近使い始めました。
Markdownで書くことができ、GitHub等のサービスにリモートリポジトリを作って PITCHME.md を置いておくとスライドにしてくれます。
詳しくは GitHubだけで超高機能なスライド資料が作れる「GitPitch」の使い方を徹底解説! - paiza開発日記

作った経緯

ただこのサービス、GitHubにpushしないとスライドの状態にならないのです。
ちょっと編集してプレビューを見たい人間なのでそれだと面倒くさいなーっと思い

というTweetをしたところ

っと来たので「おーあるやんけー」って思ってリンクを見に行ったら

スクリーンショット 2019-03-23 0.47.08.png

有料やんけ!!

っということで作りました。

構成

ローカルで実行するためにoffline版を使います。
スクリーンショット 2019-03-23 0.49.33.png

このoffline版はcorsとかの問題でhttpサーバに乗っけて配信しないとダメっぽいです。
なので、dockerでnginxを起動させそれに乗っけます。

このoffline版はスライドの生成に assets/md/PITCHME.md を参照しているのでローカルの PITCHME.md と共有するようにしました。

しかし、 docker run でボリュームを設定するさいに nginxが配信するディレクトリ /usr/share/nginx/html/assets/md/PITCHME.md を設定するのは面倒なので、 /usr/share/nginx/html/assets/md/PITCHME.md/src/PITCHME.md のシンボリックリンクにすることにしました。 これでボリュームを設定するときは -v $(pwd):/src:ro みたいな感じで設定できます。

どうしても別の場所に設定したいと言うときは、 docker runcommandPITCHME.md を絶対パスで指定してください。

使い方

上でゴチャゴチャ書いてあるものをまとめると

$ docker run -v $(pwd):/src -p 8080:80 -d uzimaru0000/gitpitch_local

でサーバが起動します。
あとは、手元の PITCHME.md を編集すれば反映されます。

課題

即席で作ったのでいろいろと課題があって

  • ---?code=path で指定したときの挙動がダメ
  • スーパーリロードしないと更新されないときがある
  • styleの適応が未実装

他にも本サイトで見るときと挙動が変わる部分が多々あると思います。
気がついた方は、リポジトリにissueを立てたり、PRを出してくれるとありがたいです。

最後に

ライセンスとかよく分からないのでもしかしたらOUTかもしれないです。その時は言ってください。消します。

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

docker-composeでfirebase functionsのローカル実行を試してみたメモ

概要

環境

  • Windows10
  • virtualbox 6.0.4
  • vagrant 2.2.4
  • Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-29-generic x86_64)
  • Docker version 18.09.2, build 6247962
  • docker-compose version 1.23.2, build 1110ad01

ファイル構成

- bin
  - firebase
    - serve-functions-local.sh # 実行用のコマンドを書いたシェル
- docker
  - docker-compose.yml
  - firebase
    - Dockerfile
    - functions
      - package.json # backendフォルダと同じもの。2重管理やめたい。。
- backend
  - functions
    - tsconfig.json
    - tslint.json
    - package.json # dockerフォルダと同じもの。2重管理やめたい。。
    - src
      - index.ts
- app
  - firebase.json

ファイル

docker関係の設定

docker/docker-compose.yml
version: '3'
services:
  garden_firebase:
    build: ./firebase
    volumes:
      - ../backend/functions:/app/functions
      - /app/functions/node_modules # コンテナ内のnode_modulesを使用
      - ../app/.firebaserc:/app/.firebaserc
      - ../app/firebase.json:/app/firebase.json
    ports:
      - 5000:5000
      - 9005:9005

functions: Cannot start emulator. Error: Cannot find module '@google-cloud/functions-emulator/src/configとでたので、パッケージをグローバルに1つ追加している。

docker/firebase/Dockerfile
FROM node:8.15.1-alpine 

# コンテナ上の作業ディレクトリ作成
WORKDIR /app

# 後で確認出来るようにpackage.jsonを作成
RUN npm init -y

# firebase
RUN yarn global add firebase-tools
RUN yarn add --dev firebase-tools

RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"firebase\": \"firebase\", /g" /app/package.json

# firebase function 
COPY functions /app/functions

# functions用のモジュールをインストールしておく。
RUN cd /app/functions && NODE_ENV=development npm install -y

# ローカルでfunctionを実行するために必要
RUN yarn global add @google-cloud/functions-emulator --ignore-engines

firebase functionsの設定

以下のpackage.jsonは2重管理となってしまっている。ポイントはfirebase serve --only functions -p 5000 -o 0.0.0.0でホストをグローバルにしているところ。コンテナ外からアクセスするために必要。

docker/firebase/functions/package.json
{
  "name": "functions",
  "scripts": {
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase serve --only functions -p 5000 -o 0.0.0.0",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.2.1"
  },
  "devDependencies": {
    "tslint": "^5.12.0",
    "typescript": "^3.2.2"
  },
  "engines": {
    "node": "8"
  },
  "private": true
}
/app/firebase.json
{
  "functions": {
    "source": "functions",
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  }
}

functionsのソース

/backend/functions/src/index.ts
import * as functions from 'firebase-functions';
export const hello = functions.https.onRequest((request, response) => {
  response.status(200).send("Hello World")
});

実行コマンド

bin/firebase/local-functions-serve.sh
#!/bin/bash

# このシェルスクリプトのディレクトリの絶対パスを取得。
bin_dir=$(cd $(dirname $0) && pwd)

# docker-composeの起動
cd $bin_dir/../../docker && docker-compose run -p 9005:9005 -p 5000:5000 garden_firebase sh -c 'cd /app/functions && npm run serve'

実行

./bin/firebase/serve-functions-local.shで実行。
画面に以下のように出てきたら成功。

✔  functions: hello: http://0.0.0.0:5000/{ここはそれぞれ違います}/us-central1/hello

vagrantで起動しているならば、そこのIPにhttp://{IPアドレス}:5000/{ここはそれぞれ違います}/us-central1/helloとアクセスすればHello Worldが表示されるはず。

functions設定時点

参考

[Firebase] Cloud Functionsで消耗したくない人のために、開発環境のベストプラクティスをまとめていったらDockerに行き着いた話(随時更新)
ローカルでのファンクションの実行
firebaseローカルサーバ起動時にfunctions: Cannot start emulator. Error: Cannot find module '@google-cloud/functions-emulator/src/configと返された。
Firebase Cloud Function をローカルで実行するときにはまった点
Cloud Functions for Firebaseが最高だった話
DockerでのNodeアプリ構築で学んだこと
firebase-functions-test を使って Firestore の offline テストを書いてみる
Cloud Functions for Firebaseを楽々デバッグするには

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