20200228のdockerに関する記事は14件です。

【Rails】Rails6系とMySQL8系の組み合わせの開発環境をDockerだけでつくる

概要

  • :point_right: この記事は弊社ァ内で行った準備作業の備忘録メモでございますわっ
  • 次の新規案件に備え、RubyとRails最新版のスケルトン(?)なプロジェクトを準備する
  • 各バージョンは以下の予定
    • Ruby2.7系
    • Rails6.0系
    • MySQL8.0系
    • Nginx1.17系
    • redis(いちおう)
  • Docker前提です
    • 新規ならDockerでしょ?って、僕も過激派になっている感。
    • AWS ECSでの運用が前提のため。
  • Rubyのイメージはalpine3.11を使用。カーネル5.4系でセキュリティも向上してるらしい(?)し、軽い1

    $ docker images
    REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
    ruby                      2.7-slim-buster     b913dc62d63c        10 days ago         149MB
    ruby                      2.7-buster          0c1ee6efe061        10 days ago         842MB
    ruby                      2.7-alpine3.10      78005ca97a7f        2 weeks ago         52.9MB
    ruby                      2.7-alpine3.11      1f7033feacdb        3 weeks ago         53.5MB
    
  • docker-compose化する。最終的にはね。

    • そこだけ読みたいならここまでスクロール

やりたいこと

  • 作業PC的な観点で
    • PCローカル内のモダンな過去プロジェクトを汚さずに環境構築したい。
    • PCローカル内のレガシーな過去プロジェクトを汚さずに環境構築したい。
    • PCローカル内のヴィンテージな過去プロジェクトを汚さずに環境構築したい。
    • PC内のパッケージに悪影響が出ないようにしたい。
  • rails new すらもDockerの中でやりたい。
  • dockerコンテナ落としてもDBの内容やbundleのgemが消えないようにしたい。
  • 他の開発者(後輩くん)が使える程度のものを残しておきたい。
  • 運用想定的な観点で(何様)
    • 環境作成
      • AP,DBコンテナの構成で十分
      • rails new してソースコード準備したい
      • できれば動作確認したい
    • 開発環境(弊社ァ内エンジニア用)
      • WEB,AP,DBコンテナに加えてRedisも建てたい
        • ↑↑環境差異による不具合を減らすため、本番環境にできるだけ合わせたい・・・!!(切実)
      • docker-compose化しておいて、少しでも普段遣いのコマンドを減らしたい
    • 本番環境
      • AWS ECSで動かす想定
      • dockerイメージはできるだけ開発環境そのままECRにプッシュする
        • 環境変数だけで環境変えたいよね
      • ECSタスク定義とかRDS設定はdocker-compose見ればほぼ設定できるようにしておきたい

Railsプロジェクトの新規作成

目的

  • docker内でrails newしてWebアプリケーションのソースを用意する
  • ここの見出しでやるのはrails newだけ。開発環境整える方法は次の見出しまでスクロールしてね

やることを決める

  • dockerボリュームの有効活用
    • 環境構築途中で失敗してもdbとgemを消さないようにして時短。
    • dockerのマウントタイプは bind でわなく volume を使う2。Macのファイルシステムへのマウントは遅い(?)ので
  • 動作確認のためDBコンテナも建てる

事前準備

docker network(一時) を作成

$ # host OS (local PC)
$ # コンテナ間通信用のネットワークを用意しておく
$ 
$ APP_NETWORK=tmp_network # 名前をきめてね
$ 
$ docker network create ${APP_NETWORK}
$ 
$ # 確認しよう
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c31a38da01e0        tmp_network         bridge              local

docker volume(一時) を作成

$ # host OS (local PC)
$ # DBデータ保持用と、gem保存用の2つのdockerボリュームを作っておく。
$ 
$ DB_VOLUME=tmp_dbdata_vol # 名前をきめてね
$ BUNDLE_VOLUME=tmp_bundle_vol # 名前をきめてね
$ 
$ docker volume create ${DB_VOLUME}
$ docker volume create ${BUNDLE_VOLUME}
$ 
$ # 確認しよう
$ docker volume ls
DRIVER              VOLUME NAME
local               tmp_bundle_vol
local               tmp_dbdata_vol
  • これ以降のコンテナ作成作業中で、エラーが出まくったら、volumeを一度作り直すなどして問題解決していこうかと考えていた。

コンテナの作成

DBコンテナ(一時)を建てる

  • mysqld コマンドのオプションで色々宣言している。 **.cnfを用意するのでも良かったけど、本番はRDS使うだろうし、
$ # host OS (local PC)
$ 
$ # パスワードはあくまで一例。ちゃんと毎回違うランダム文字を使う癖をつけるように教えるの()
$ docker run \
    --detach \
    --env MYSQL_ROOT_PASSWORD=4h%zpW8wrb+G \
    --env TZ="Asia/Tokyo" \
    --mount type=volume,source=${DB_VOLUME},target=/var/lib/mysql \
    --name tmp_db_mysql \
    --network ${APP_NETWORK} \
    --publish 127.0.0.1:13306:3306 \
    --tty \
    mysql:8.0 \
    mysqld \
      --block_encryption_mode aes-256-cbc \
      --character_set_server utf8mb4 \
      --collation-server utf8mb4_bin \
      --default-authentication-plugin mysql_native_password \
      --explicit_defaults_for_timestamp \
      --init-connect 'SET NAMES utf8mb4' \
      --skip-character-set-client-handshake

APコンテナ(一時)を建てる

$ # host OS (local PC)
$ 
$ # DBパスワードはDBコンテナと同じもの
$ docker run \
    --detach \
    --env APP_DATABASE_PASSWORD=4h%zpW8wrb+G \
    --mount type=volume,source=${BUNDLE_VOLUME},target=/usr/local/bundle \
    --name tmp_ap_rails \
    --network ${APP_NETWORK} \
    --publish 127.0.0.1:3000:3000 \
    --tty \
    --workdir /app \
    ruby:2.7-alpine3.11

プロジェクトの新規作成

Railsプロジェクトを新規作成

$ # host OS (local PC)
$ 
$ docker exec -it tmp_ap_rails sh
/app # # guest OS (ruby:2.7-alpine3.11)
/app # 
/app # # 必要そうなパッケージをAlpineLinuxPackagesからインストール
/app # apk update
/app # apk upgrade
/app # apk add --update --no-cache \
          build-base \
          git \
          imagemagick \
          imagemagick-dev \
          libxml2-dev \
          libxslt-dev \
          mysql-client \
          mysql-dev \
          nodejs \
          ruby-dev \
          tzdata \
          yarn
/app # 
/app # # yarnのインストールコマンドを叩いておく
/app # yarn install
  • ローカルPC内でGemfileを作って、それをAPコンテナ(一時)にコピーする
  • ここでrailsのバージョンを決めている
Gemfile
source 'https://rubygems.org'

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails', '~> 6.0', '>= 6.0.2.1'
$ # host OS (local PC)
$ 
$ # cpコマンドでdocker内にファイルをコピーする
$ docker cp Gemfile tmp_ap_rails:/app/Gemfile
$ # host OS (local PC)
$ 
$ docker exec -it tmp_ap_rails sh
/app # # guest OS (ruby:2.7-alpine3.11)
/app #
/app # # railsをインストールする
/app # bundle install
/app #
/app # rails --version
Rails 6.0.2.1
/app #
/app # # Railsプロジェクトを新規作成する(各オプションはプロジェクトに応じて変える)
/app # rails new . \
      --database=mysql \
      --force \
      --skip-coffee \
      --skip-sprockets \
      --skip-turbolinks \
      --skip-test \
      --webpack=vue

設定値の書き換え

/app # # guest OS (ruby:2.7-alpine3.11)
/app #
/app # # development と test の設定を変更
/app # vi config/database.yml
config/database.yml
# --- L20..L24
development:
  <<: *default
  database: app_development
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: tmp_db_mysql
# --- L29..L33
test:
  <<: *default
  database: app_test
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: tmp_db_mysql

動作確認

/app # # guest OS (ruby:2.7-alpine3.11)
/app #
/app # rails db:create
/app #
/app # rails server -b 0.0.0.0

スクリーンショット 2020-02-21 18.37.09.png

  • うまく、いった、みたい、

ソースコードのコピー

  • ディレクトリ内をコピーするときは . をつけるらしい3
  • この作業で新規プロジェクトのソースコードがローカルPCにコピーされるので、これをgithubで管理するなりしておく
$ # host OS (local PC)
$ 
$ # Docker内のソースコードをホスト側にコピーする
$ docker cp tmp_ap_rails:/app/. ./

ゴミ掃除

APコンテナ(一時)の削除

  • APコンテナ(一時)は rails new と動作確認のためだけのコンテナだったので、消す。
$ # host OS (local PC)
$ 
$ docker stop tmp_ap_rails
$ docker rm tmp_ap_rails
$ 
$ # 消えていることを確認
$ docker ps -a

DBコンテナ(一時)の削除

  • DBコンテナ(一時)も、消す。
$ # host OS (local PC)
$ 
$ docker stop tmp_db_mysql
$ docker rm tmp_db_mysql
$ 
$ # 消えていることを確認
$ docker ps -a

docker network(一時)の削除

  • docker network(一時)も、消す。
$ # host OS (local PC)
$ 
$ docker network rm ${APP_NETWORK}
$ 
$ # 消えていることを確認
$ docker network ls

docker volume(一時)の削除

  • docker volume(一時)も、消す。
$ # host OS (local PC)
$ 
$ docker volume rm ${DB_VOLUME}
$ docker volume rm ${BUNDLE_VOLUME}
$ 
$ # 消えていることを確認
$ docker volume ls

Railsプロジェクトの新規作成まとめ

  • 長文になってしまって申し訳ナソス
  • ローカルPCのrubyバージョンに影響されずにrailsプロジェクトが新規作成できた。
    • (rbenvとかを使用してもこの程度はできる気がするけど・・・)
  • これを応用してエンジニア用の開発環境も整えていく形で良さそう。(何様)
  • 上記に記してはいないが、volume設定でgemを別に保持できていたのを確認できているので、感触はOK
    • 直接volume内を見に行くのは少々面倒だが、bindよりは動作速そう(?)。

docker-compose化

目的

  • ここから先が本当にやりたかったことやで。。。
  • 上記までの準備(新規作成したrailsプロジェクト)をもとに、開発環境(弊社ァ内エンジニア用)を整えてゆく

やることを決める

  • docker-compose.ymlを用意する
  • 基本 docker-compose up -d, docker-compose down コマンドだけで動くようにしておく
  • ログローテートはちゃんと設定する(もし無限ログ吐き出されてもPCをパンクさせない教訓)
  • Dockerfileの用意をしてビルド時には必要パッケージがインストールされている状態にする
    • Dockerfileはマルチステージビルド4を仕込んでおき、本番リリースに使えるようにしておく
  • WEBコンテナ(nginx)を追加して、静的ページを表示できるようにする
    • 静的ファイル、ソケットはAPコンテナとつなげておく
      • ソケットはrails6だからpuma(unixソケットにする予定)
    • 起動順の依存関係には一番最後
  • CACHEコンテナ(redis)を追加しておく
    • 起動順の依存関係はAPより前
    • 今回は使わないけど。開発で使うので

Dockerfileの作成

containers/web/Dockerfile
FROM nginx:1.17-alpine

LABEL maintainer="なまえ <メアド>"

# 設定ファイルを上書き
RUN rm -f /etc/nginx/conf.d/*
ADD ./containers/web/default.conf /etc/nginx/conf.d/default.conf

# nginxの起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
containers/web/default.conf
# @note ホストサーバーとのファイル共有は以下
#   - tmp/     # pumaソケット通信用
#   - public/  # rails静的ファイル共有(404ページとかjs,cssとか)

# nginxとpumaのソケット通信の設定
# @see{https://github.com/puma/puma/blob/master/docs/nginx.md}
upstream rails_app {
  server unix:///rails_app/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name localhost;

  # HTTPの持続的な接続維持時間(軽量なので0秒(off)でもいいかも)
  keepalive_timeout 5;

  # アップロードサイズの上限を設定
  client_max_body_size 10m;

  # 静的ファイルのパス
  root /rails_app/public;

  # ログ出力(dockerイメージの設定より、このパスは標準出力となる)
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log info;

  # メンテナンスファイルが置かれている場合はメンテ画面を出す
  if (-f $document_root/maintenance.html) {
    rewrite  ^(.*)$  /maintenance.html last;
    break;
  }

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

    # 静的ファイル
    if (-f $request_filename) {
      break;
    }

    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }

    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }

    if (!-f $request_filename) {
      proxy_pass http://rails_app;
      break;
    }
  }

  # 後方一致で画像などの静的ファイルが指定された場合はpublic/配下のファイルを直接返す(Railsを介さない)
  location ~* \.(ico|css|gif|jpe?g|png|js)(\?[0-9]+)?$ {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

    # ファイルパスが存在しない場合はRailsで処理
    if (!-f $request_filename) {
      proxy_pass http://rails_app;
      break;
    }

    expires max;
    break;
  }
}
  • ↓↓マルチステージビルドの使い方が完全に自己流なんだけどこれで良いのかしら・・・。
containers/app/Dockerfile
FROM ruby:2.7-alpine3.11 as dev_mode

LABEL maintainer="なまえ <メアド>"

# ビルド時の作業ディレクトリ
WORKDIR /app

# AlpineLinuxPackagesで必要そうなコマンドをインストール
RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache \
        build-base \
        git \
        imagemagick \
        imagemagick-dev \
        libxml2-dev \
        libxslt-dev \
        mysql-client \
        mysql-dev \
        nodejs \
        ruby-dev \
        tzdata \
        yarn

# yarnインストールの実行(先にlockファイルをコピーしてバージョンを固定)
COPY package.json yarn.lock ./
RUN yarn install

# マルチステージビルドで本番用イメージを作成
FROM dev_mode as prod_mode

# Railsの秘密情報のマスターキー(docker build時にオプションで宣言する)
ARG RAILS_MASTER_KEY
ENV RAILS_MASTER_KEY ${RAILS_MASTER_KEY}
# 本番モードで起動する
ENV RAILS_ENV production

# アプリのソースをイメージ内にコピー
COPY ./ ./

RUN bundle install

# フロント用のライブラリのインストールと静的ファイルの作成
RUN rails yarn:install
RUN rails webpacker:compile

# コンパイル後、マスターキー情報はイメージから消しておく
ENV RAILS_MASTER_KEY=

docker-compose.ymlの作成

  • 2020/02くらいに確認したときは、バージョン3.7が最新だった5ので、それで。
  • パスワードはあくまで一例。
docker-compose.yml
version: '3.7'

# @see {https://docs.docker.com/compose/compose-file/}
services:
  # DBコンテナの設定
  db:
    # ビルドに使うイメージ
    image: mysql:8.0
    # 環境変数
    environment:
      MYSQL_DATABASE: app_development
      MYSQL_ROOT_PASSWORD: F-O75%kSG6gz
      TZ: "Asia/Tokyo"
    # ログローテート設定
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # コンテナ間通信用
    networks:
      - app_net
    # ホストOSに開放するポートの指定
    ports:
      - 127.0.0.1:3306:3306
    # ファイルのマウント設定
    volumes:
      # データベースの内容をDocker領域に同期する(データ永続化のため)
      - type: volume
        source: mysql_data_vol
        target: /var/lib/mysql
    # コンテナを永続化
    tty: true
    # 認証を旧式(パスワード)に変更、デフォルトの文字コードとcollate設定を指定、暗号化のモード選択
    command: >
      mysqld
      --block_encryption_mode aes-256-cbc
      --character_set_server utf8mb4
      --collation-server utf8mb4_bin
      --default-authentication-plugin mysql_native_password
      --explicit_defaults_for_timestamp
      --init-connect 'SET NAMES utf8mb4'
      --skip-character-set-client-handshake

  # Redisコンテナの設定
  redis:
    # ビルドに使うイメージ
    image: redis
    # ログローテート設定
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # コンテナ間通信用
    networks:
      - app_net
    # コンテナを永続化
    tty: true

  # APコンテナの設定
  app:
    # ビルド時の設定
    build:
      # プロジェクトのディレクトリでビルドする
      context: .
      # マルチステージビルドのターゲットを指定
      target: dev_mode
      # Dockerfileの場所を指定
      dockerfile: containers/app/Dockerfile
    # コンテナ依存関係
    depends_on:
      - db
      - redis
    # 環境変数
    environment:
      APP_DATABASE_PASSWORD: F-O75%kSG6gz
      # RAILS_MASTER_KEY:
      # RAILS_MAX_THREADS:
      TZ: "Asia/Tokyo"
    # ログローテート設定
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # コンテナ間通信用
    networks:
      - app_net
    # ファイルのマウント設定
    volumes:
      # アプリのソースをホストOSと共有する
      - type: bind
        source: .
        target: /app
      # gemをDocker領域に同期する
      - type: volume
        source: bundle_vol
        target: /usr/local/bundle
    # コンテナを永続化
    tty: true
    # bundle install 、yarn install を行い、pumaサーバーを起動する
    command: >
      sh -c "
      bundle install &&
      rails yarn:install &&
      rails webpacker:compile &&
      pumactl start"

  # WEBコンテナの設定
  web:
    # ビルド時の設定
    build:
      # プロジェクトのディレクトリでビルドする
      context: .
      # Dockerfileの場所を指定
      dockerfile: containers/web/Dockerfile
    # コンテナ依存関係
    depends_on:
      - app
    # ログローテート設定
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # ホストOSに開放するポートの指定
    ports:
      - 127.0.0.1:80:80
    # ファイルのマウント設定
    volumes:
      # 静的ファイルの共有
      - type: bind
        source: ./public
        target: /rails_app/public
      # pumaソケットファイルの共有
      - type: bind
        source: ./tmp
        target: /rails_app/tmp

# ネットワークの定義
networks:
  # コンテナ間通信用
  app_net:

# ボリュームの定義
volumes:
  mysql_data_vol:
  bundle_vol:
  • rails側のDB設定も修正修正(ホストをdocker-composeで定義した名前に変えよう)
config/database.yml
# --- L20..L24
development:
  <<: *default
  database: app_development
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: db
# --- L29..L33
test:
  <<: *default
  database: app_test
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: db
  • あと、WEBコンテナとソケット通信させるためにconfigも少し修正が必要だった6
config/puma.rb
# --- L13
# unixソケット通信はポートを使用しない
# port        ENV.fetch("PORT") { 3000 }

# --- 最後に追加
# ソケット通信の設定(WORK_DIRを/appにしているからもう直書きで良いかしら)
bind "unix:///app/tmp/sockets/puma.sock"

動作確認

$ # host OS (local PC)
$ 
$ # いよいよdocker-compose起動するぜ!!
$ docker-compose up -d
$ 
$ # 確認
$ docker-compose ps
        Name                       Command               State                  Ports
----------------------------------------------------------------------------------------------------
skl_rails6021_app_1     sh -c  bundle install && r ...   Up
skl_rails6021_db_1      docker-entrypoint.sh mysql ...   Up      127.0.0.1:3306->3306/tcp, 33060/tcp
skl_rails6021_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
skl_rails6021_web_1     /bin/sh -c /usr/sbin/nginx ...   Up      127.0.0.1:80->80/tcp
$ 
$ # 確認
$ docker-compose logs --tail 30 app
$ docker-compose logs --tail 30 web
$ 
$ # MySQLもローカルPCから接続できるよね
$ mysql -u root -p
  • ローカルPCで http://localhost:80 にアクセス(初回は時間がかかるのでログを見て落ち着いたら)

スクリーンショット 2020-02-28 20.23.46.png

  • うまく、できた、みたい、

READMEに説明を書く

  • やる。
  • 僕だけ使えても意味がない。
  • もしかしたらこの作業が一番骨折れるかもしれない。

最後に

  • 長文失礼。
  • ポート開放不親切失礼。必要に応じて書き換え願う
  • ruby2.7対応していないgemがいくつかあるみたいで、ログが汚い。warningの大量発生や。。。(2020/02ころ現在)
  • WEBコンテナ追加してnginxとソケット通信する作業でに労力増えてる感ある。rails severのありがたみを感じる。。。
  • redisの設定は開発時にやるで良いよね。。。

  1. https://hub.docker.com/_/ruby ←←2020/02くらいにここを閲覧した、そして全部取得して比べてみた。 

  2. https://docs.docker.com/storage/volumes/ ←Docker領域内に名前つけて保存されるから、万が一ソースコードごと紛失してもワンチャンある() 

  3. https://medium.com/veltra-engineering/how-to-copy-a-directory-using-docker-cp-command-f2c73f9ccf75 ←←こちらのサイトがとても参考になりました :pray::pray::pray: 

  4. https://docs.docker.com/develop/develop-images/multistage-build/#use-a-previous-stage-as-a-new-stage 

  5. https://docs.docker.com/compose/compose-file/compose-versioning/ 

  6. https://github.com/puma/puma#binding-tcp--sockets unixソケットにするためにbindのオプションをconfig/puma.rbに書く必要があった。こことかこれとかこのへん読んでも書き方迷いそう。。。 

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

dockerでwordpress環境を構築する

dockerでwordpress環境を構築する

dockerを使ってwordpress環境を構築しました。

前提

  • dockerはインストール済み

やったこと

1.wordpress実行用のdocker networkをつくる

docker network create wp-net

wp-netとした。

2.作成したwp-netネットワークに参加させる形でmysqlのコンテナを起動する

run --name cp-mysql --network wp-net -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:$(WPの推奨バージョンを指定する)

3.2で起動したコンテナのIPアドレスを調べる

docker network  inspect wp-net

1で起動したコンテナを探してIPv4Addressの値をメモる

4.wp-net上にwordpressのコンテナを起動する。

今回はホストの8080ポートをWebアクセスの入り口としてバインドする

docker run --name wordpress3 --network wp-net  -e WORDPRESS_DB_PASSWORD=$(1で指定したDBパスワード)  -e WORDPRESS_DB_HOST=$(3でメモったIPアドレス) -p 8080:80  -d wordpress

5.ブラウザで開く

http://localhost:8080/
をお好きなブラウザで開く
開いたら成功。めでたしめでたし

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

初めてのWEBアプリ作成(1)

はじめに

 初めまして、RHEMS技術研究室所属の白瀬です。
今回は初めてWEBアプリ作成としてTrello風ToDoリストを作成するまでの工程を投稿していこうと思います。間違った点がありましたらご指摘いただけると嬉しいです。
環境はmacのdocker,iTerms2を使用しています。

コンテナ構築

 nginx・PHP・MYSQLのコンテナの構築をdockerで行いました。!
今回はnginxとPHPの連携させずに作って行きます。
(無題).png

全体のディレクトリ

├── docker-compose.yml
├── nginx
│   └── nginx.conf
├── php
│   ├── Dockerfile
│   └── php.ini
├── mysql
│   └── data
└── www
    └── html
        └── index.php

コマンド

docker-compose.yml

version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./www/html:/var/www/html
    depends_on:
      - php

  php:
    build: ./php
    volumes:
      - ./www/html:/var/www/html
    depends_on:
      - db

  db:
    image: mysql:5.7
    ports:
      - 13306:3306
    volumes:
      - ./mysql/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret


nginx.conf

server {
    listen 80;
    server_name _;

    root  /var/www/html;
    index index.php index.html;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;    
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

Dockerfile

FROM php:7.2-fpm
COPY php.ini /usr/local/etc/php/

php.ini

date.timezone = "Asia/Tokyo"

index.php

<h1>Hello WORLD</h1>

すべて書き終えた後docker-compose.ymlがあるディレクトリまで移動し下記のコマンドを実行

docker-compose up -d

実行し終えたらlocalホスト(http://localhost:8080/)に接続して画像のようになりました。
スクリーンショット 2020-02-28 16.44.01.png
残りはこれをToDoリストように書き換えていくだけだと思っています。

あとがき

自分がWEBアプリを作ってみてくれ言われ何をしたらいいか分からずdocker trello 作成などといった検索をかけていましたが的はずれなことをしていました。
誰でもはじめはわからないことばかりなので皆さんも人に聞きましょう。
自分は4日ほど悩んでました…

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

コンテナ上のpython27/pyodbcでホストのSQL Serverにアクセスする

概要

先日の以下の記事でmysqlにアクセスする方法をご紹介しましたが、
コンテナ上のpython3/mysql-connector-pythonでホストのmysqlにアクセスする
SQL serverバージョンをご紹介します。

前提

ホストSQL Server

ODBC Driver 17 for SQL Server
SQLServer認証でポート1443で動作している

手順

ODBCが動くDockerコンテナの作り方の記事内にある以下のリポジトリをcloneします。
https://github.com/Microsoft/mssql-docker/tree/master/oss-drivers/pyodbc

> git clone https://github.com/microsoft/mssql-docker.git
> cd mssql-docker/oss-drivers/pyodbc

以下のツリーになっていると思います。

pyodbc
├── Dockerfile
├── README.md
├── docker-compose.yml *docker-composeで立ち上げるために追加
├── entrypoint.sh
└── sample.py *編集します。もしくは別ファイルを作ってもよいです。touch入ってませんが...
Dockerfile
# mssql-python-pyodbc
# Python runtime with pyodbc to connect to SQL Server
FROM ubuntu:16.04

# apt-get and system utilities
RUN apt-get update && apt-get install -y \
    curl apt-utils apt-transport-https debconf-utils gcc build-essential g++-5\
    && rm -rf /var/lib/apt/lists/*

# adding custom MS repository
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list

# install SQL Server drivers
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y msodbcsql unixodbc-dev

# install SQL Server tools
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y mssql-tools
RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
RUN /bin/bash -c "source ~/.bashrc"

# python libraries
RUN apt-get update && apt-get install -y \
    python-pip python-dev python-setuptools \
    --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

# install necessary locales
RUN apt-get update && apt-get install -y locales \
    && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
    && locale-gen
RUN pip install --upgrade pip

# install SQL Server Python SQL Server connector module - pyodbc
RUN pip install pyodbc

# install additional utilities
RUN apt-get update && apt-get install gettext nano vim -y

# add sample code
RUN mkdir /sample
ADD . /sample
WORKDIR /sample

CMD /bin/bash ./entrypoint.sh
docker-compose.yaml
version: '3'
services:
  pyodbc:
    restart: always
    build: .
    container_name: 'pyodbc'
    working_dir: '/sample'
    tty: true
    volumes:
      - .:/sample
    extra_hosts:
      - "(ホストのCOMPUTERNAME):(ホストのIPアドレス)"
    ports:
      - 1443:1443
sample.py
import pyodbc


server = '(ホストのIPアドレス),(ホストのSQLServer動作ポート)'
username = 'sa'
password = 'password'

cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';database=(データベース名);UID='+username+';PWD='+password)
cursor = cnxn.cursor()

print ('Using the following SQL Server version:')
tsql = "SELECT @@version;"
with cursor.execute(tsql):
    rows = cursor.fetchall()
    for row in rows:
        print(str(row))

> docker-compose up -d --build
...
> docker container ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
2c51574bfd36        pyodbc_pyodbc       "/bin/sh -c '/bin/ba…"   51 minutes ago      Up 51 minutes       0.0.0.0:1443->1443/tcp   pyodbc
> docker exec -it 2c51574bfd36 /bin/bash
$ python --version
Python 2.7.12
$ python sample.py
Using the following SQL Server version:
(u'Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) \n\tAug 22 2017 17:04:49 \n\tCopyright (C) 2017 Microsoft Corporation\n\tExpress Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 18362: ) (Hypervisor)\n', )

結果

無事SQL ServerにアクセスしDB参照できました。

後日談(2020/2/28追記内容)

ヒアドキュメントを文字列代入した時にエラー発生

変更内容

sample.py
tsql = '''\
    SELECT *
FROM
    ~
INNER JOIN
    ~
ON
'''

エラー内容

$ python sample.py 
  File "sample.py", line 17
SyntaxError: Non-ASCII character '\xe7' in file sample.py on line 18, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

  File "sample.py", line 54, in <module>
    with cursor.execute(tsql):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 48: ordinal not in range(128)

試行した手順

以下の記事で解決しましませんでした。
http://shu223.hatenablog.com/entry/20111201/1328334689

以下の記事で解決しませんでした。
https://qiita.com/chatrate/items/eb4b05cd1a6652529fd9

解決した手順

以下を参考にしたら解決しました。
https://kaworu.jpn.org/python/Python%E3%81%AEUnicodeDecodeError%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95

sample.py
- with cursor.execute(tsql):
+ with cursor.execute(tsql.decode('utf-8')):

後日談改(2020/2/29追記内容)

ホストのIPアドレス可変に対応

コンテナ内からhost.docker.internalとかいうホストOSに%COMPUTERNAME%さしてくれるエイリアスがあるみたいです。

docker-compose.yml
-    extra_hosts:
-      - "(ホストのCOMPUTERNAME):(ホストのIPアドレス)"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitLab-CIで「ERROR: Job failed (system failure): Error: No such container」が発生

現象

GitLab-CIのジョブが、ある日突然下記のようなエラーを吐いてFailedになるようになった。
この状態では、同じジョブはリトライしても高確率で失敗。(たまに成功しているジョブもあるのが難解)

gitlab-runnerはDocker版を使用しており、Docker Executorとしてセットアップしたもの。

ERROR: Job failed (system failure): Error: No such container: 40c002093a4bd596c73a19aa006b80b552d728d76128654cf65f3ac4967fdac3 (executor_docker.go:785:0s)

調査

エラー内容で調べていると、この投稿にたどり着いた。

下記のような操作が有効とのこと。

  1. Dockerのサービスを止める
  2. すべてのイメージを削除する
  3. ディスク領域を開放する
  4. Dockerとgitlab-runnerのサービスを起動する

対処

ディスク領域が逼迫している様子はなかったので、私の場合は2や3は関係ないような気がした。

そのため、とりあえずgitlab-runnerのコンテナを稼働させているVMを再起動させてみることに。
この操作に伴って、上記の1や4の操作を実施することになる。

再起動後は、正常に動作していることを確認。

安易に再起動できない環境の場合は、必要に応じて上記1~4の操作を試してみると良さそう。

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

TDD失敗事例(次回に活きれば)

まとめ

いきなりですが、私がTDDを実施するために必要だと感じたこと(今回足りなかったこと)
1. 詳細設計所(もしくは十分な業務知識の理解。何を作ってるのか?)
2. 単体テストをするための準備(繰り返し実行しても同じ結果が返ること。DB定義の更新があった場合取り込めて、データの作成の手間が最小になるような環境に出来るのが理想。どうやるのがベストなのか、まだわかりません)
3. 体制準備(テストがオールグリーンじゃないとpushできないくらいの強制力のある仕組みを用意してもいいかも)
4.pullrequestの単位を小さくすること(単位がでかすぎると結局どういうコードがあって、どんなテストがされてるのかわからない。初めにテストを書かせて、どんなテストをするかレビューした後にコード実装に入ってもいいかも)

なぜTDD?

  • 既存のソースコード改修してリリース->予想外の場所でエラーが・・・
  • メソッドが長すぎて何やってんのかよくわからん
  • とりあえず実装したけどバグがやばい!

    こんなときにTDDで開発すればきれいさっぱり解決します!
    (今回私は完全に達成できなかったのですが、体感として一部あります。)

メリットデメリット(書籍の内容&私が感じたこと)

メリット デメリット
1. メソッドが最小になりやすい。
2.既存のコード改修時に既存の振る舞いに変更がないことを確認しやすい。
3.業務ロジックがわかる(テストを記述するためにはどういうテストが必要か?を知る必要があり、最低限の業務を理解している必要がある)
4.リファクタリングが容易
1.コード量が倍になる
2.テストを書きなれていないと時間がかかる(個人差あると思います。)
3.それなりに技術力が必要(どんなテストがあるのか?)
4.既存コードへの適用は大変

当たり前かもしれませんが、テストを書いて、ちゃんとグリーンで通ってるよねってことが確認できてもそれが必ずしも業務要件や、パフォーマンス、ユーザビリティを保証しているものではないので、そこは別途注意が必要だと思います。

失敗したこと(こうなって欲しくないこと)

  • ソースレビュー時にテスト長すぎてバーがグリーンになるけど結局何やってるかわからない
  • 単体テストがかけるレベルの詳細設計所を書けなかった。ざっくりとした要件で伝えてしまったので、テストは全てグリーンになっていたが、業務要件が満たせていなかった。
  • 単体テストをする環境作り。個人の環境で何回実行しても同一のテストが繰り返しグリーンになるようなDBおよびテストデータ作りの十分な知見がなく、それをするための環境の整備ができなかった。
  • プロジェクトが炎上したときにテストコードを最後まで書ききることができない部分があった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker run -it の「-it」とはなにか

Docker, コマンド操作の初心者向けに書いています.

Docker コンテナを起動するとき, docker run -it ubuntu:18.04 bash と入力したりする……,
-it とはいったい何か, という話です.

-it は オプション -i と -t の指定

-it と入力した場合,
-i or --interactive-t or --tty 2つのオプションを指定したという意味です.

(標準化されたものか分かりませんが一般的に)
-i はショートオプション, --interactive はロングオプション
と呼ばれます.

docker run -it ...docker run -i -t ...
この2つの指定は同じです.

docker run コマンドに限らず, 多くのコマンドでこういったオプション指定ができるようになってます.
(たとえばgrep. 大文字小文字を無視, ディレクトリ再帰, バイナリを無視を指定する場合の grep -irIgrep -i -r -I と同じ)

interactive (-i, --interactive) オプションは入力のこと

interactive オプションは, 「入力」のことです.
もうちょっと具体的には「標準入力」のことです. 次のものが相当します.

  • キー入力
  • パイプされたデータ
  • ファイルからのリダイレクト

例を出します.

「seqコマンドの結果を, DockerのUbuntuイメージに入っているawkコマンドを使って偶数だけ出力するようフィルタしたい」
とします.

# seqコマンドの結果
$ seq 10
1
2
3
4
5
6
7
8
9
10

その場合は, パイプと docker run -i コマンドを組み合わせれば実現できる, ということになります.

$ seq 10 | docker run -i ubuntu:18.04 awk '$1 % 2 == 0'
2
4
6
8
10

もうちょっと実用的な例をだします.

「作成したPythonスクリプトを, DockerのPythonイメージを使って実行したい」

ほとんどの場合は, volumeオプションでローカルPCのディレクトリを, Dockerコンテナに共有させて実行させますが,
場合によっては, リダイレクトが使えます.

# Pythonスクリプトの中身
$ cat hoge.py
print("hello")

# PythonスクリプトをDockerコンテナのPythonにリダイレクトして実行
$ docker run -i python:3.7 python < hoge.py
hello

tty (-t, --tty) オプションは疑似端末

ここ, ちょっとちゃんと理解できてないところもあるのですが, ttyは「端末」のことです.
ここでいう端末は, たとえばプロンプトが表示されたbash/zsh などのインタラクティブシェルのことです.
REPLを備えたPythonなどもそうです.
コマンドを入力できて, 実行できて, 即座に実行結果が表示されるアレです.

たとえば, Ubuntuのコンテナを起動すると同時に top コマンドを実行して監視してみたい

-t オプション指定がないと, 「TERM環境変数が設定されていない」というエラーがでて
起動すらできません.

$ docker run --rm ubuntu:18.04 top
TERM environment variable not set.

docker run に -t オプションを指定すると, topを起動できるようになります.
ちなみに, -t だけの指定で -i がないとキー入力が受け付けられなくなるため,
Qキー押下で終了できません.
(topコマンドはCtrl-C で割り込んで止められましたが,
起動するインタラクティブシェルによっては, それすらできないません.
別のターミナルでdockerコマンドを使ってコンテナを終了/停止する必要があります)

類似のオプションは他のソフトウェアにもあったりします.

たとえば, sshで接続した先でコマンドを実行する場合,
ssh $xxx_host program のように実行コマンドを指定します.

この実行コマンドがインタラクティブシェル/REPLである場合は (インタラクティブシェルとして使いたい場合は), -t を指定する必要があります.
ssh -t $xxx_host python のように.

まとめ (というほどではないけど)

  • -i オプションだけ指定することが有用なケースはそれなりにある
  • -t オプションだけ指定する状況はちょっと思いつかない

参考資料

http://docs.docker.jp/engine/reference/run.html

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

docker コマンドだけで起動する proxy サーバ

proxy という npm パッケージを node コンテナで実行するだけでお手軽に proxy サーバが起動できる。

コマンド

$ docker run --rm -p 8888:3128 node npx proxy 
  • proxy コマンドはデフォルトで 3128 ポートをListenするのでそれをホスト側の 8888 にポートマッピングしている

ブラウザの設定(Firefoxの場合)

Image from Gyazo

  • Manual Proxy setting でホスト名を localhost、ポート番号を先のコマンドでポートマッピングしたportに設定

参考

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

GitLab-CI + Cypressで自動テストを実行すると、レンダラーのクラッシュで異常終了

背景

以前の投稿GitLab-CICypressを連携して、Webアプリケーションの自動テスト環境を構築した。

当初は何ら問題なく動いていたが、ある時から以下のエラーを吐いてパイプラインがFailedになるようになってしまった。

本投稿では、その対処方法を掲載する。

We detected that the Chromium Renderer process just crashed.

This is the equivalent to seeing the 'sad face' when Chrome dies.

This can happen for a number of different reasons:

- You wrote an endless loop and you must fix your own code
- There is a memory leak in Cypress (unlikely but possible)
- You are running Docker (there is an easy fix for this: see link below)
- You are running lots of tests on a memory intense application
- You are running in a memory starved VM environment
- There are problems with your GPU / GPU drivers
- There are browser bugs in Chromium

You can learn more including how to fix Docker here:

https://on.cypress.io/renderer-process-crashed

環境

  • CentOS 7.5.1804
  • GitLab CE 11.11.3
  • gitlab-runner v12.6.0
  • Cypress v3.7.0

調査

ヒントは、エラーメッセージ末尾に書かれていた。

You can learn more including how to fix Docker here:
https://on.cypress.io/renderer-process-crashed

リンクを辿ると最終的にGitHubのIssueスレッドにたどり着く。
スレッドを読むと、この投稿に解決策が記載されていた。

対処

1. gitlab-runnerのconfigを修正

修正すべきファイルは、gitlab-runnerのコンテナの中であれば/etc/gitlab-runner/config.toml、コンテナ作成時にvolumesを指定してホストOS側のパスをマウントしている場合は、そのファイルを直接編集すると良い。

config.toml
[[runners]]
  ...
  executor = "docker"
  ...
  [runners.docker]
   ...
    volumes = ["/dev/shm:/dev/shm", ...other volumes...]
  ...
  [runners.cache]

2. gitlab-runnerを再起動

# ホストOSから実行する場合
docker exec gitlab-runner-docker gitlab-runner restart

# コンテナにログイン後に実行する場合
gitlab-runner restart
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Quorumのサンプル動作

はじめに

「Ethereumは使ったことがあるけど、Ethereum Enterprise版を使ったことがない。」
「Quorumを聞いたことはあるが、使ったことがない。」

という人向けです。

Ethereum Enterprise版の Quorum の動かし方を学びます。

Quorumとは

Quorum は、トランザクション/コントラクトのプライバシーと新しいコンセンサスメカニズムを備えたイーサリアムベースの分散台帳プロトコルです。

クォーラムはgo-ethereumのフォークであり、go-ethereumのリリースに合わせて更新されます。

リンクまとめ

主要な機能

  • Privacy: Quorumは、パブリック/プライベート状態の分離を通じてプライベートトランザクションとプライベートコントラクトをサポートし、P2P暗号化メッセージ交換(ConstellationおよびTesseraを参照)を使用して、プライベートデータをネットワーク参加者に直接転送します
  • Alternative Consensus Mechanisms: 許可されたネットワークでPOW / POSを使用する必要がないため、Quorumは代わりに、コンソーシアムチェーンにより適した複数のコンセンサスメカニズムを提供します。
    • Raft-based Consensus: ブロック時間、トランザクションの最終性、およびオンデマンドブロック作成を高速化するためのコンセンサスモデル
    • Istanbul BFT: AMISによるトランザクションの最終性を備えたPBFTにヒントを得たコンセンサスアルゴリズム。
  • Peer Permissioning: スマートコントラクトを使用したノード/ピアの許可。既知の関係者のみがネットワークに参加できるようにします。
  • Higher Performance: Quorumは、公開gethよりも大幅に高いパフォーマンスを提供します

ダウンロード

Quorum のサンプルを Git から取得します。

$ git clone https://github.com/jpmorganchase/quorum-examples
$ cd quorum-examples

動作確認

Dockerで立ち上げます。

$ docker-compose up -d

Dockerが立ち上がったか確認してみましょう。

$ docker ps

CONTAINER ID        IMAGE                                   COMMAND                   CREATED             STATUS                            PORTS                                                                           NAMES
86c1fe5b22fc        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22002->8545/tcp   quorum-examples_node3_1
7a495a567f8d        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22000->8545/tcp   quorum-examples_node1_1
1d7079247b29        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22005->8545/tcp   quorum-examples_node6_1
be5a3f8e5a0e        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22003->8545/tcp   quorum-examples_node4_1
7deb7a02d97a        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 6 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22001->8545/tcp   quorum-examples_node2_1
d483ea254c41        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22006->8545/tcp   quorum-examples_node7_1
cf8c85e59cd6        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 6 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22004->8545/tcp   quorum-examples_node5_1
4c22e504b943        quorumengineering/cakeshop:0.11.0-RC2   "/bin/sh -c 'DDIR=/q…"    12 seconds ago      Up 7 seconds (health: starting)   8080/tcp, 8102/tcp, 0.0.0.0:8999->8999/tcp                                      quorum-examples_cakeshop_1
de2c803c03c1        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9085->9080/tcp                                                quorum-examples_txmanager5_1
f39fb0103c4f        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9081->9080/tcp                                                quorum-examples_txmanager1_1
aa4f16bf26bc        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9083->9080/tcp                                                quorum-examples_txmanager3_1
2b964d12ba0c        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9084->9080/tcp                                                quorum-examples_txmanager4_1
29276e52b8c4        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9086->9080/tcp                                                quorum-examples_txmanager6_1
04c87773a143        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9082->9080/tcp                                                quorum-examples_txmanager2_1
a94c254ca903        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9087->9080/tcp                                                quorum-examples_txmanager7_1

Nodeへのアクセス

次のコマンドは、docker-compose up -dで立ち上げてから、数分経過しないとエラーになります。。。
また、エラーにならなくても、consoleが出るまでに数分かかります。

$ docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc

Welcome to the Geth JavaScript console!

instance: Geth/node1-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xd8dba507e85f116b1f7e231ca8525fc9008a6966
at block: 6 (Thu, 27 Feb 2020 10:06:16 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

エラー時は以下、エラーの時はすぐに出力されます。

$ docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
panic: MustNew: Failed to connect to Constellation (/qdata/tm/tm.ipc): lstat /qdata/tm/tm.ipc: no such file or directory

goroutine 1 [running]:
github.com/ethereum/go-ethereum/private/constellation.MustNew(0xc00003800f, 0x10, 0xc00003800f)
    /go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/private/constellation/constellation.go:108 +0x1de
github.com/ethereum/go-ethereum/private.FromEnvironmentOrNil(0x11bbb1d, 0xe, 0xc0001ef5a0, 0xc0001ef580)
    /go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/private/private.go:20 +0x64

コントラクトのデプロイ

コンソールに入って、下記のコマンドを実行し、コントラクトをチェーン上へデプロイします。(これもコンソールが立ち上がってから通るまでに、数分かかりました。。。)

> loadScript('/examples/private-contract.js')
Contract transaction send: TransactionHash: 0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74 waiting to be mined...
true
> Contract mined! Address: 0x1932c48b2bf8102ba33b4a6b545c32236e342f34
[object Object]

生成したトランザクションの中身を確認してみましょう。

> eth.getTransaction("0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74")
{
  blockHash: "0x1d678eac0ebf0a7c3c2b2f222f93190d8f27a3951129c397857ddf2a190f51df",
  blockNumber: 19,
  from: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
  gas: 4700000,
  gasPrice: 0,
  hash: "0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74",
  input: "0x2fb0476e23e90ac27f7a202550f6497e967b80a5776cbf9475a14f562a61b213ec7d914302c3a948d8f459c160adbfaf2a2c9a2e4f6eb5b750746de4f3df7c3e",
  nonce: 0,
  r: "0xbe181b4eaad9559338f49cae1a8add46938518f7f582bd26e19ed06dab73b8e1",
  s: "0x5fcd1eb6afa30c1277b2cf7fb8a0b11fd0a85796637f2992955ec88da8eb0046",
  to: null,
  transactionIndex: 0,
  v: "0x25",
  value: 0
}

コントラクトを生成できたので、Node1からコントラクトへアクセスしてみましょう。

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
42

42が取得できていることがわかります。

他の Node からのコントラクトへアクセス

同様に、node4 と node7 から取得できるかを確認してみます。

Node4

$ docker exec -it quorum-examples_node4_1 geth attach /qdata/dd/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/node4-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xf512a992f3fb749857d758ffda1330e590fa915e
at block: 320 (Thu, 27 Feb 2020 10:27:12 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> private.get()
ReferenceError: 'private' is not defined
    at <anonymous>:1:1

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
0

Node7

$ docker exec -it quorum-examples_node7_1 geth attach /qdata/dd/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/node7-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xb131288f355bc27090e542ae0be213c20350b767
at block: 407 (Thu, 27 Feb 2020 10:29:38 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
42

node4からは0、node7からは42が取得されています。

動作のまとめ

したがって、ノード1と7がプライベートコントラクトの状態を読み取ることができ、その初期値は42です。
private-contract.jsを見ると、42の値がコントラクトの作成時に設定された値であることがわかります。
ノード4は状態を読み取ることができません。

コントラクトの値の書き換え

node1 のコンソールで下記のように設定すると、値が書き換わります。

> private.set(4,{from:eth.accounts[0],privateFor:["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]});
"0x189a5755c0a1104445cb83a4689221494794832ab6e6cefa5ee6a02696fc38ac"
> private.get()
4

これを、Node4 と Node7 から確認したのが下記です。

Node4

> private.get()
0

Node7

> private.get()
4

Node1, Node7 からアクセスできて、Node4からはアクセスできていないことがわかります。

Permissions

Node Permissioningは、事前に定義された一連のノード(remotekey / enodesで識別される)のみが許可されたネットワークに接続できるようにするQuorumの機能です。

geth attach path/to/geth.ipcで個々のノードに接続し、接続されたノードを確認するためにadmin.peersを使用します。

> admin.peers
[{
    caps: ["istanbul/64"],
    enode: "enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d70f684688fb7cf@172.16.239.17:40062",
    id: "3cb4aaea0f49f73c9de4a34db131288f355bc27090e542ae0be213c20350b767",
    name: "Geth/node7-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.17:40062",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@172.16.239.12:54236",
    id: "995dbe18829f1affb75402e66571d97f340c8495b661a823f2c2145ca47d63c2",
    name: "Geth/node2-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.12:54236",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1167,
        head: "0xd8ff13d791864d599dbed913f416af92413cc2422ebe9f3e14bb575c795c5728",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a62257f82737a8cffc80474c15c611c037f52db1a3a7b@172.16.239.16:21000?discport=0&raftport=50400",
    id: "ab62dd7df5863a5f3bb61f458157d4437104e3b8df4451a85f7b2438ef6699ff",
    name: "Geth/node6-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:52212",
      remoteAddress: "172.16.239.16:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@172.16.239.13:21000?discport=0&raftport=50400",
    id: "c39143f98d04e97bd9e31ac1e36cbeb565b061217930767886474e3cde903ac5",
    name: "Geth/node3-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:43438",
      remoteAddress: "172.16.239.13:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1167,
        head: "0xd8ff13d791864d599dbed913f416af92413cc2422ebe9f3e14bb575c795c5728",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@172.16.239.14:21000?discport=0&raftport=50400",
    id: "c75f7dcb9fd6063f0ada0998f512a992f3fb749857d758ffda1330e590fa915e",
    name: "Geth/node4-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:47280",
      remoteAddress: "172.16.239.14:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1166,
        head: "0xdb21189404e3e5d8c111ca1ced00f149033bedcd9c23e844c12ac149c47b9b49",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b41693880ea0cb@172.16.239.15:59474",
    id: "f06c06f1e958cb2edf90d8bfb912de287f9b047b4228436e94b5b78e3ee16171",
    name: "Geth/node5-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.15:59474",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}]

Permissions の構成

gethノードのリモートキーに基づいて許可が付与されます。リモートキーpermissioned-nodes.jsonはで指定され、個々のノードの<datadir>の下に配置されます。

permissioned-nodes.json
[
  "enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401",
  "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402",
  "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@127.0.0.1:21002?discport=0&raftport=50403",
  "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@127.0.0.1:21003?discport=0&raftport=50404",
  "enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b41693880ea0cb@127.0.0.1:21004?discport=0&raftport=50405",
  "enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a62257f82737a8cffc80474c15c611c037f52db1a3a7b@127.0.0.1:21005?discport=0&raftport=50406",
  "enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d70f684688fb7cf@127.0.0.1:21006?discport=0&raftport=50407"
]

Permissions の有効化/無効化

個々のノードは、gethを立てる際に-permissionedコマンドラインフラグを渡すことで許可を有効または無効にできます。
有効になっている場合、<datadir>/permissioned-nodes.jsonのノードのみが接続できます。
さらに、これらは、このノードがアウトバウンド接続を行うことができる唯一のノードです

終わりに

サンプルだけでは少々物足りないですね。
もっと調査します。

Nodeについて調査しました。
https://qiita.com/ryu3/items/2552a0a48e3e5164aa26

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

Quorum

はじめに

「Ethereumは使ったことがあるけど、Ethereum Enterprise版を使ったことがない。」
「Quorumを聞いたことはあるが、使ったことがない。」

という人向けです。

Ethereum Enterprise版の Quorum の動かし方を学びます。

Quorumとは

Quorum は、トランザクション/コントラクトのプライバシーと新しいコンセンサスメカニズムを備えたイーサリアムベースの分散台帳プロトコルです。

クォーラムはgo-ethereumのフォークであり、go-ethereumのリリースに合わせて更新されます。

リンクまとめ

主要な機能

  • Privacy: Quorumは、パブリック/プライベート状態の分離を通じてプライベートトランザクションとプライベートコントラクトをサポートし、P2P暗号化メッセージ交換(ConstellationおよびTesseraを参照)を使用して、プライベートデータをネットワーク参加者に直接転送します
  • Alternative Consensus Mechanisms: 許可されたネットワークでPOW / POSを使用する必要がないため、Quorumは代わりに、コンソーシアムチェーンにより適した複数のコンセンサスメカニズムを提供します。
    • Raft-based Consensus: ブロック時間、トランザクションの最終性、およびオンデマンドブロック作成を高速化するためのコンセンサスモデル
    • Istanbul BFT: AMISによるトランザクションの最終性を備えたPBFTにヒントを得たコンセンサスアルゴリズム。
  • Peer Permissioning: スマートコントラクトを使用したノード/ピアの許可。既知の関係者のみがネットワークに参加できるようにします。
  • Higher Performance: Quorumは、公開gethよりも大幅に高いパフォーマンスを提供します

ダウンロード

Quorum のサンプルを Git から取得します。

$ git clone https://github.com/jpmorganchase/quorum-examples
$ cd quorum-examples

動作確認

Dockerで立ち上げます。

$ docker-compose up -d

Dockerが立ち上がったか確認してみましょう。

$ docker ps

CONTAINER ID        IMAGE                                   COMMAND                   CREATED             STATUS                            PORTS                                                                           NAMES
86c1fe5b22fc        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22002->8545/tcp   quorum-examples_node3_1
7a495a567f8d        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22000->8545/tcp   quorum-examples_node1_1
1d7079247b29        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22005->8545/tcp   quorum-examples_node6_1
be5a3f8e5a0e        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    9 seconds ago       Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22003->8545/tcp   quorum-examples_node4_1
7deb7a02d97a        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 6 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22001->8545/tcp   quorum-examples_node2_1
d483ea254c41        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 5 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22006->8545/tcp   quorum-examples_node7_1
cf8c85e59cd6        quorumengineering/quorum:2.4.0          "/bin/sh -c 'UDS_WAI…"    10 seconds ago      Up 6 seconds (health: starting)   8546/tcp, 21000/tcp, 30303/tcp, 50400/tcp, 30303/udp, 0.0.0.0:22004->8545/tcp   quorum-examples_node5_1
4c22e504b943        quorumengineering/cakeshop:0.11.0-RC2   "/bin/sh -c 'DDIR=/q…"    12 seconds ago      Up 7 seconds (health: starting)   8080/tcp, 8102/tcp, 0.0.0.0:8999->8999/tcp                                      quorum-examples_cakeshop_1
de2c803c03c1        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9085->9080/tcp                                                quorum-examples_txmanager5_1
f39fb0103c4f        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9081->9080/tcp                                                quorum-examples_txmanager1_1
aa4f16bf26bc        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9083->9080/tcp                                                quorum-examples_txmanager3_1
2b964d12ba0c        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9084->9080/tcp                                                quorum-examples_txmanager4_1
29276e52b8c4        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 8 seconds (health: starting)   9000/tcp, 0.0.0.0:9086->9080/tcp                                                quorum-examples_txmanager6_1
04c87773a143        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9082->9080/tcp                                                quorum-examples_txmanager2_1
a94c254ca903        quorumengineering/tessera:0.10.3        "/bin/sh -c 'if [ \"$…"   12 seconds ago      Up 9 seconds (health: starting)   9000/tcp, 0.0.0.0:9087->9080/tcp                                                quorum-examples_txmanager7_1

Nodeへのアクセス

次のコマンドは、docker-compose up -dで立ち上げてから、数分経過しないとエラーになります。。。
また、エラーにならなくても、consoleが出るまでに数分かかります。

$ docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc

Welcome to the Geth JavaScript console!

instance: Geth/node1-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xd8dba507e85f116b1f7e231ca8525fc9008a6966
at block: 6 (Thu, 27 Feb 2020 10:06:16 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

エラー時は以下、エラーの時はすぐに出力されます。

$ docker exec -it quorum-examples_node1_1 geth attach /qdata/dd/geth.ipc
panic: MustNew: Failed to connect to Constellation (/qdata/tm/tm.ipc): lstat /qdata/tm/tm.ipc: no such file or directory

goroutine 1 [running]:
github.com/ethereum/go-ethereum/private/constellation.MustNew(0xc00003800f, 0x10, 0xc00003800f)
    /go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/private/constellation/constellation.go:108 +0x1de
github.com/ethereum/go-ethereum/private.FromEnvironmentOrNil(0x11bbb1d, 0xe, 0xc0001ef5a0, 0xc0001ef580)
    /go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/private/private.go:20 +0x64

コントラクトのデプロイ

コンソールに入って、下記のコマンドを実行し、コントラクトをチェーン上へデプロイします。(これもコンソールが立ち上がってから通るまでに、数分かかりました。。。)

> loadScript('/examples/private-contract.js')
Contract transaction send: TransactionHash: 0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74 waiting to be mined...
true
> Contract mined! Address: 0x1932c48b2bf8102ba33b4a6b545c32236e342f34
[object Object]

生成したトランザクションの中身を確認してみましょう。

> eth.getTransaction("0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74")
{
  blockHash: "0x1d678eac0ebf0a7c3c2b2f222f93190d8f27a3951129c397857ddf2a190f51df",
  blockNumber: 19,
  from: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
  gas: 4700000,
  gasPrice: 0,
  hash: "0xcca72b49194d7d1a90746ac0cc9f50c1ac870b8c914d2079c044e7b7065abd74",
  input: "0x2fb0476e23e90ac27f7a202550f6497e967b80a5776cbf9475a14f562a61b213ec7d914302c3a948d8f459c160adbfaf2a2c9a2e4f6eb5b750746de4f3df7c3e",
  nonce: 0,
  r: "0xbe181b4eaad9559338f49cae1a8add46938518f7f582bd26e19ed06dab73b8e1",
  s: "0x5fcd1eb6afa30c1277b2cf7fb8a0b11fd0a85796637f2992955ec88da8eb0046",
  to: null,
  transactionIndex: 0,
  v: "0x25",
  value: 0
}

コントラクトを生成できたので、Node1からコントラクトへアクセスしてみましょう。

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
42

42が取得できていることがわかります。

他の Node からのコントラクトへアクセス

同様に、node4 と node7 から取得できるかを確認してみます。

Node4

$ docker exec -it quorum-examples_node4_1 geth attach /qdata/dd/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/node4-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xf512a992f3fb749857d758ffda1330e590fa915e
at block: 320 (Thu, 27 Feb 2020 10:27:12 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> private.get()
ReferenceError: 'private' is not defined
    at <anonymous>:1:1

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
0

Node7

$ docker exec -it quorum-examples_node7_1 geth attach /qdata/dd/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/node7-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13
coinbase: 0xb131288f355bc27090e542ae0be213c20350b767
at block: 407 (Thu, 27 Feb 2020 10:29:38 UTC)
 datadir: /qdata/dd
 modules: admin:1.0 debug:1.0 eth:1.0 istanbul:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34"
undefined
> var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"type":"constructor"}];
undefined
> var private = eth.contract(abi).at(address)
undefined
> private.get()
42

node4からは0、node7からは42が取得されています。

動作のまとめ

したがって、ノード1と7がプライベートコントラクトの状態を読み取ることができ、その初期値は42です。
private-contract.jsを見ると、42の値がコントラクトの作成時に設定された値であることがわかります。
ノード4は状態を読み取ることができません。

コントラクトの値の書き換え

node1 のコンソールで下記のように設定すると、値が書き換わります。

> private.set(4,{from:eth.accounts[0],privateFor:["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]});
"0x189a5755c0a1104445cb83a4689221494794832ab6e6cefa5ee6a02696fc38ac"
> private.get()
4

これを、Node4 と Node7 から確認したのが下記です。

Node4

> private.get()
0

Node7

> private.get()
4

Node1, Node7 からアクセスできて、Node4からはアクセスできていないことがわかります。

Permissions

Node Permissioningは、事前に定義された一連のノード(remotekey / enodesで識別される)のみが許可されたネットワークに接続できるようにするQuorumの機能です。

geth attach path/to/geth.ipcで個々のノードに接続し、接続されたノードを確認するためにadmin.peersを使用します。

> admin.peers
[{
    caps: ["istanbul/64"],
    enode: "enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d70f684688fb7cf@172.16.239.17:40062",
    id: "3cb4aaea0f49f73c9de4a34db131288f355bc27090e542ae0be213c20350b767",
    name: "Geth/node7-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.17:40062",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@172.16.239.12:54236",
    id: "995dbe18829f1affb75402e66571d97f340c8495b661a823f2c2145ca47d63c2",
    name: "Geth/node2-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.12:54236",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1167,
        head: "0xd8ff13d791864d599dbed913f416af92413cc2422ebe9f3e14bb575c795c5728",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a62257f82737a8cffc80474c15c611c037f52db1a3a7b@172.16.239.16:21000?discport=0&raftport=50400",
    id: "ab62dd7df5863a5f3bb61f458157d4437104e3b8df4451a85f7b2438ef6699ff",
    name: "Geth/node6-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:52212",
      remoteAddress: "172.16.239.16:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@172.16.239.13:21000?discport=0&raftport=50400",
    id: "c39143f98d04e97bd9e31ac1e36cbeb565b061217930767886474e3cde903ac5",
    name: "Geth/node3-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:43438",
      remoteAddress: "172.16.239.13:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1167,
        head: "0xd8ff13d791864d599dbed913f416af92413cc2422ebe9f3e14bb575c795c5728",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@172.16.239.14:21000?discport=0&raftport=50400",
    id: "c75f7dcb9fd6063f0ada0998f512a992f3fb749857d758ffda1330e590fa915e",
    name: "Geth/node4-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: false,
      localAddress: "172.16.239.11:47280",
      remoteAddress: "172.16.239.14:21000",
      static: true,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1166,
        head: "0xdb21189404e3e5d8c111ca1ced00f149033bedcd9c23e844c12ac149c47b9b49",
        version: 64
      }
    }
}, {
    caps: ["istanbul/64"],
    enode: "enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b41693880ea0cb@172.16.239.15:59474",
    id: "f06c06f1e958cb2edf90d8bfb912de287f9b047b4228436e94b5b78e3ee16171",
    name: "Geth/node5-istanbul/v1.8.18-stable-20c95e5d(quorum-v2.4.0)/linux-amd64/go1.11.13",
    network: {
      inbound: true,
      localAddress: "172.16.239.11:21000",
      remoteAddress: "172.16.239.15:59474",
      static: false,
      trusted: false
    },
    protocols: {
      istanbul: {
        difficulty: 1169,
        head: "0x765088e2cea778a865703c5a057398ce6d4d5d62de8785e8ae898547da0ac4c8",
        version: 64
      }
    }
}]

Permissions の構成

gethノードのリモートキーに基づいて許可が付与されます。リモートキーpermissioned-nodes.jsonはで指定され、個々のノードの<datadir>の下に配置されます。

permissioned-nodes.json
[
  "enode://ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef@127.0.0.1:21000?discport=0&raftport=50401",
  "enode://0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416@127.0.0.1:21001?discport=0&raftport=50402",
  "enode://579f786d4e2830bbcc02815a27e8a9bacccc9605df4dc6f20bcc1a6eb391e7225fff7cb83e5b4ecd1f3a94d8b733803f2f66b7e871961e7b029e22c155c3a778@127.0.0.1:21002?discport=0&raftport=50403",
  "enode://3d9ca5956b38557aba991e31cf510d4df641dce9cc26bfeb7de082f0c07abb6ede3a58410c8f249dabeecee4ad3979929ac4c7c496ad20b8cfdd061b7401b4f5@127.0.0.1:21003?discport=0&raftport=50404",
  "enode://3701f007bfa4cb26512d7df18e6bbd202e8484a6e11d387af6e482b525fa25542d46ff9c99db87bd419b980c24a086117a397f6d8f88e74351b41693880ea0cb@127.0.0.1:21004?discport=0&raftport=50405",
  "enode://eacaa74c4b0e7a9e12d2fe5fee6595eda841d6d992c35dbbcc50fcee4aa86dfbbdeff7dc7e72c2305d5a62257f82737a8cffc80474c15c611c037f52db1a3a7b@127.0.0.1:21005?discport=0&raftport=50406",
  "enode://239c1f044a2b03b6c4713109af036b775c5418fe4ca63b04b1ce00124af00ddab7cc088fc46020cdc783b6207efe624551be4c06a994993d8d70f684688fb7cf@127.0.0.1:21006?discport=0&raftport=50407"
]

Permissions の有効化/無効化

個々のノードは、gethを立てる際に-permissionedコマンドラインフラグを渡すことで許可を有効または無効にできます。
有効になっている場合、<datadir>/permissioned-nodes.jsonのノードのみが接続できます。
さらに、これらは、このノードがアウトバウンド接続を行うことができる唯一のノードです

終わりに

サンプルだけでは少々物足りないですね。
もっと調査します。

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

Dockerコンテナ内でpingを実行するための備忘録

pingコマンドが実行できなかったため、以下でインストールしようとしましたが、できませんでした。

apt-get install iputils-ping

エラー、、、

E: Unable to locate package iputils-ping
E: Unable to locate package net-tools

以下で、インストール可能なパッケージの一覧を最新にしたのち、再びインストールを行ったらできました。

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

Docker Desktop for Windows (参考訳)

Docker Desktop for Windows

原文ウェブ版原文
2020年2月27日現在の情報です。

目次

Docker for Windows を始めよう

Docker Desktop へようこそ!

Docker Desktop for Windows のセクションで扱う情報は、Docker Desktop コミュニティ安定版リリース(Community Stable release)に関してです。エッジリリース(Edge release)に関する情報は、 エッジリリースノートを御覧ください。Docker デスクトップ・エンタープライズ(DDE)リリースに関する情報は Docker Desktop Enterprise を御覧ください。

Docker とは、コンテナ化したアプリケーションを構築・実行・共有するための、全てが揃った開発プラットフォームです。Windows 上で Docker を使い始めるためには、Docker Desktop が最も良い方法です。

ダウンロード情報、システム要件、インストール手順については、 Docker Desktop のインストール を御覧ください。

インストールの確認

  1. ターミナルウインドウを開きます(コマンドプロンプトか PowerShellの場合 。ただし、PowerShell ISE は除く)。
  2. docker --version を実行し、サポート対象の Docker かどうかを確認します。
> docker --version

Docker version 19.03.1

3. hello-world イメージ を Docker Hub から取得し、コンテナとして実行します。

> docker run hello-world

docker : Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:c3b4ada4687bbaa170745b3e4dd8ac3f194ca95b2d0518b417fb47e5879d9b5f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

4. Docker Hub からダウンロードした hello-world イメージを、一覧から確認します。

> docker image ls

5. hello-world コンテナを一覧に表示します("Hello from Docker!" を表示した後、終了 exited しています)。

> docker container ls --all

6. いくつかのヘルプ命令を実行し、Docker ヘルプページを見て回ります。

> docker --help
> docker container --help
> docker container ls --help
> docker run --help

アプリケーションを試す

このセクションでは、OS やウェブサーバといった複雑なアプリケーションを実行し、Docker 化アプリケーションの簡易さと威力をお見せします。

  1. Ubuntu OS のイメージを取得し、作成したコンテナ内で、双方向(インタラクティブ)のターミナルを実行します。
> docker run --interactive --tty ubuntu bash

docker : Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
22e816666fd6: Pull complete
079b6d2a1e53: Pull complete
11048ebae908: Pull complete
c58094023a2e: Pull complete
Digest: sha256:a7b8b7b33e44b123d7f997bd4d3d0a59fafc63e203d17efedf09ff3f6f516152
Status: Downloaded newer image for ubuntu:latest

**PowerShell ISE を使用しないでください* 双方向ターミナルは PowerShell ISE では動作しません(PowerShell では動作します)。詳細は docker/for-win/issues/223 を御覧ください

2. コンテナの中にいます。ルート # プロンプト上で、コンテナの hostname (ホスト名)を確認します。

root@8aea0acb7423:/# hostname
8aea0acb7423

ホスト名には、コンテナ ID が割り当てられているのに注目します(プロンプトでもホスト名にコンテナ ID が用いられています)。

3. exit コマンドでシェルを終了します(また、コンテナも停止します)。

root@8aea0acb7423:/# exit
>

4. --all オプションを付けて、コンテナ一覧を表示します(実行中のコンテナが存在しないからです)。

hello-world コンテナ(ランダムに relaxed_sammet と名前付け)は、自身のメッセージを表示した後、停止しました(stopped)。 ubuntu コンテナ(ランダムに laughing_kowalevski と名前付け)は、コンテナから抜け出た(exit)ので停止しました(stopped)。

> docker container ls --all

CONTAINER ID    IMAGE          COMMAND     CREATED          STATUS                      PORTS    NAMES
8aea0acb7423    ubuntu         "bash"      2 minutes ago    Exited (0) 2 minutes ago             laughing_kowalevski
45f77eb48e78    hello-world    "/hello"    3 minutes ago    Exited (0) 3 minutes ago             relaxed_sammet

5. Docker 化した nginx (エンジンエックス)ウェブ・サーバを取得・実行し、 webserver と名付けます。

> docker run --detach --publish 80:80 --name webserver nginx

Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx

fdd5d7827f33: Pull complete
a3ed95caeb02: Pull complete
16f7a5f3082: Pull complete
7b10f03a0309: Pull complete
Digest: sha256:f6a001272d5d324c4c9f3f183e1b69e9e0ff12debeb7a092730d638c33e0de3e
Status: Downloaded newer image for nginx:latest
dfe13c68b3b86f01951af617df02be4897184cbf7a8b4d5caf1c3c5bd3fc267f

6. ウェブ・ブラウザで http://localhost を指定し、nginx のスタートページを開きます( :80 を追加する必要はありません。 docker コマンドで標準の HTTP ポートを指定したからです)。

<図>

7. 実行中( running )のコンテナのみを一覧表示します。

> docker container ls

CONTAINER ID    IMAGE    COMMAND                   CREATED          STATUS          PORTS                 NAMES
0e788d8e4dfd    nginx    "nginx -g 'daemon of…"    2 minutes ago    Up 2 minutes    0.0.0.0:80->80/tcp    webserver

8. 実行中の nginx コンテナを停止するために、割り当てた webserver の名前を使います。

> docker container stop webserver

9. 3つのコンテナ全てを、名前で削除します。後ろにある2つの名前は、おそらく皆さんの環境とは異なるでしょう。

> docker container rm webserver laughing_kowalevski relaxed_sammet

Docker 設定画面(ダイアログ)

Docker Desktop のメニュー から、インストール、アップデート、バージョンチャンネル、Docker Hub へのログインなど、Docker の設定ができます。

このセクションでは、 Settings (設定)画面から設定できるオプションについて説明します。

1. Docker Desktop のメニューを開くには、通知エリア(又はシステムトレイ)にある Docker アイコンをクリックします。

<図>

2. 設定画面から Settings (設定)を選びます。

<図>

General(一般的な設定)

設定画面の General タブでは、Docker の起動と更新を設定できます。

<図>

  • Start Docker when you log in - Windows システムへのログイン時、自動的に Docker Desktop を起動します。
  • Automatically check for updates - デフォルトでは、Docker Desktop は自動的に更新を確認し、更新版が利用可能な場合は通知します。承諾して更新版をインストールするには OK をクリックします(あるいは、現在のバージョンを維持する場合は、キャンセルします)。メインの Docker メニューから Check for Updates (更新を確認)で、手動での更新ができます。
  • Expose daemon on tcp://localhost:2357 without TLS - レガシー(古い)クライアントが Docker デーモンに接続できるようにするには、このオプションを有効化します。このオプションを使う場合は注意が必要です。TLS なしでデーモンを公開する場合は、リモートからのコード実行攻撃をもたらす可能性があるためです。
  • Send usage statics - デフォルトでは、Docker Desktop は診断情報・クラッシュ報告・利用データを送信します。この情報は、 Docker の改善やアプリケーションの問題解決に役立ちます。止めるにはチェックボックスを空にします。Docker は定期的に更なる情報を訊ねるかもしれません。

Resources(リソース)

Resources タブは、CPU、メモリ、ディスク、プロキシ、ネットワーク、その他のリソースを設定できます。

<図>

ADVANCED(高度な設定)

Advanced タブでは、 Docker が利用できるリソースに制限をかけます。

  • CPUs (CPU): デフォルトでは、 ホスト・マシン上で利用可能なプロセッサ数の半分を、Docker Desktop が使います。総理能力を向上するには、この値を高くします。減らすには、数値を低くします。
  • Memory (メモリ): デフォルトでは、 マシン上で利用可能な全メモリから 2 GB の実行メモリを使用する設定です。RAM を増やすには、この値を高くします。減らすには、値を低くします。
  • Swap (スワップ): 必要になるスワップ・ファイル容量を設定します。デフォルトは 1 GB です。
  • Disk image size (ディスク・イメージ容量): ディスク・イメージの容量を指定します。
  • Disk image location (ディスク・イメージの場所): Linux ボリュームの場所を指定します。ここにコンテナとイメージを置きます。

また、ディスク・イメージは別の場所に移動できます。ディスク・イメージの指定先に既にイメージがある場合は、既存のイメージを使うか置き換えるか訊ねる画面を表示します。

FILE SHARING(ファイル共有)

Linux コンテナと共有したいローカルのディレクトリを選択します。ファイル共有は Linux コンテナ内でボリュームをマウントするために必要であり、Windows コンテナ用ではありません。Linux コンテナでは、Dockerfile とボリュームを保管するための場所として、ドライブの共有が必要です。指定がなければ、実行時に file not found (ファイルが見つかりません)や cannot start service (サービスを開始できません)のエラーが出ます。詳しくは「Linux コンテナのボリューム・マウントには共有ドライブが必要」を御覧ください。

ファイル共有権限は、ここで指定した場所に認証情報(credential)の設定を試みます。この場所に対しては、設定済みの異なるユーザ名で docker コマンドを実行しても、コンテナはマウントされたボリュームに対してアクセスできません。

コンテナに共有したいローカル・ドライブを指定したら、 Docker Desktop は Windows システム(ドメイン)のユーザ名とパスワードの入力を求めます。認証情報を入力の後、 Apply & Restart (適用と再起動)をクリックします。

共有ドライブ、権限、ボリューム・マウントに役立つ情報
- 可能であれば、Windows ホストからボリューム・マウントするのではなく、その代わりに Linux VM 上をマウントします。あるいはデータ・ボリューム(名前付きボリューム)やデータ・コンテナを使います。ホストをマウントするボリュームや、データベース・ファイルにネットワーク・パスを用いる場合、多数の問題があります。詳細は「ホスト・パスでボリュームのマウントでは、データベース・ロックを上書きする nobrl オプションを使う」を御覧ください。
- Docker Desktop はユーザ、グループ、その他に対する読み込み/書き込み/実行権限を 0777 あるいは a+rwx に設定します。これは調整できません。詳細は「共有ボリュームにおけるデータ・ディレクトリ上の権限エラー」を御覧ください。
- ドメイン・ユーザは共有ドライブにアクセスできるようにしてください。詳細な情報は「ドメイン・ユーザは共有ドライブに対する権限があるかどうか確認」を御覧ください。
- コンテナに対してはローカル・ドライブを共有可能ですが、Docker Machine ノードに対してではありません。詳細は FAQ の「Docker Machine 用仮想マシンでローカル・ドライブとファイルシステムを共有できますか?」を御覧ください。

FIREWALL RULES FOR SHARED DRIVES(共有ドライブのファイアウォール・ルール)

ホストマシンと Linux コンテナを実行する仮想マシン間では、ドライブの共有にポート 445 のオープンが必要です。共有ドライブの追加ときに、Docker でポート 445 が閉じられているのを検出したら、以下のメッセージを表示します。

<図>

ドライブを共有するには、Windows ファイアウォールやサードパーティ製のファイアウォール・ソフトウェアで、Windows ホストマシンと仮想マシン間での通信を可能にします。ポート 445 以外のネットワークは、一切開く必要がありません。

デフォルトでは、 10.0.75.2 (仮想マシン)から 10.0.75.1 上のポート 445(Windows ホスト)へと通信します。もしもファイアウォールのルールが正しければ、Hyper-V 仮想ネットワーク・カード上のファイルと印刷共有サービスの切り替え又は再インストールが必要になるかもしれません。

SHARED DRIVES ON DEMAND(オンデマンド共有ドライブ)

個々のマウントが必要な場合、初回に "オンデマンド" でドライブを共有できます。

シェルでボリューム・マウント(以下に例があります)する Docker コマンドの実行時や、Compose ファイルで立ち上げ時にボリューム・マウントがあれば、特定のドライブを共有するかどうか訊ねるポップアップが現れます。

Share it (共有する)を選択でき、Docker Desktop の「共有ドライブ一覧」にあるいずれかを、コンテナで利用可能になります。あるいは、共有したくない場合には Cancel (中止)を選べます。

<図>

PROXIES(プロキシ)

Docker Desktop は、HTTP/HTTPS プロキシ設定を調整し、自動的に Docker とコンテナに対して情報を伝達(propagate)します。例えば、 http://proxy.example.com に対してプロキシ設定をすると、Docker はコンテナの取得時にこのプロキシを使います。

コンテナが実行中であれば、コンテナ内にプロキシ設定が伝わっているかどうか確認できます。例:

> docker run alpine env

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b7edf988b2b5
TERM=xterm
HOME=/root
HTTP_PROXY=http://proxy.example.com:3128
http_proxy=http://proxy.example.com:3128
no_proxy=*.local, 169.254/16

こちらの結果では、 HTTP_PROXYhttp_proxyno_proxy 環境変数が設定されているのが分かります。プロキシ設定を変更した場合は、新しい設定を適用するために、Docker は自動的に再起動します。再起動後もコンテナを実行し続けたい場合には、「再起動ポリシー」の利用を検討すべきでしょう。

NETWORK (ネットワーク)

Docker Desktop のネットワーク機能を、仮想プライベート・ネットワーク(VPN)でも機能するように設定できます。インターネットとの疎通を有効にするには、ネットワーク・アドレス変換(NAT)プリフィックスとサブネットマスクを設定します。

DNS Server (DNS サーバ) : DNS サーバには、動的 IP アドレスか固定 IP アドレスを設定できます。

メモ : 何人かの利用者から、 Docker Desktop の安定バージョンで Docker Hub との通信問題が報告されています。これは docker コマンドの実行を試みるとき、Docker Hub からイメージを未ダウンロードであれば、エラーが確実に発生します。例えば、 docker run hello-world の初回実行時です。このような現象になれば、DNS サーバをリセットし、Google DNS の固定アドレス 8.8.8.8 を指定します。詳しい情報は「ネットワーク機能の問題」にあるトラブルシューティングを御覧ください。

以上の情報の更新するには、設定の変更と Linux VM の再起動が必要です。

Docker Engine (Docker エンジン)

Docker Engine のページでは、Docker デーモンの設定や、どのようにしてコンテナを実行するかを決められます。

デーモンの設定をするには、テキストボックス内に JSON 形式の設定ファイルとして入力します。オプションの一覧については、 Docker Engine dockerd コマンドライン・リファレンス を御覧ください。

Apply & Restart (適用と再起動)をクリックし、設定を保存して Docker Desktop を再起動します。

Command Line (コマンドライン)

コマンドラインのページでは、experimental features(実験的機能)を有効にするかどうかを指定できます。

Docker Desktop Edge と Stable リリースのいずれでも、実験的機能の有効化と無効化を切り替えできます。実験的機能を無効化すると、Docker Desktop は現時点の Docker エンジン安定版リリースを使います。

実験的機能

Docker Desktop Edge リリースは、デフォルトで Docker エンジンの実験的なバージョンが有効です。詳細は Git Hub 上の Docker 実験的機能 README(英語) を御覧ください。

実験的機能は、今後提供する機能を先行利用できます。各機能は、テストやフィードバックを意図した、参考程度のものです。そのため、リリース時までに警告が出たり、今後のリリースでは削除されたりする場合があります。本番向けの環境では、実験的機能を決して使わないでください。Docker は実験的機能に対するサポートを提供していません。

Tips: Docker コマンドラインツールで実験的機能を有効にするには、 config.json ファイルを編集し、 experimental を有効化するよう指定します。
Docker Desktop のメニューから実験的機能を有効にするには、 Settings (設定) → Command Line (コマンドライン)をクリックし、 Enable experimental features (実験的機能の有効化)ボタンを押します。 Apply & Restart (適用と再起動)をクリックします。

実験的機能が有効かどうかを確認するには、 docker version を実行します。実験的モードは Server データ下の一覧に状態があります。もしも以下のように Experimental (実験的)が true (真)であれば、Docker は実験的モードで動作しています。

> docker version

Client: Docker Engine - Community
 Version:           19.03.1
 API version:       1.40
 Go version:        go1.12.5
 Git commit:        74b1e89
 Built:             Thu Jul 25 21:17:08 2019
 OS/Arch:           windows/amd64
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.5
  Git commit:       74b1e89
  Built:            Thu Jul 25 21:17:52 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Kubernetes

Docker Desktop には単独の Kubernetes サーバを含みます。Kubernetes は Windows ホスト上で実行できますので、Kubernetes 上に Docker ワークロードを試験的にデプロイできます。

<図>

Kubernetes クライアント・コマンドの kubectl が組み込まれており、ローカルの Kubernetes サーバに接続するよう設定済みです。もしも既に kubectl をインストール済みで、 minikube や GKE クラスタのような他の環境を向いている場合は、 kubectldocker-for-desktop を指し示すように切り替わっているかどうか確認します。

> kubectl config get-contexts
> kubectl config use-context docker-for-desktop

Kubernetes サポートを有効化し、Kubernetes の独立したインスタンスを Docker コンテナとしてインストールするには、 Enable Kubernetes (Kubernetes 有効化)をクリックします。

Kubernetes を デフォルトのオーケストレータ として設定するには、 Deploy Docker Stacks to Kubernetes by default (Docker Stack のデプロイをデフォルトで Kubernetes にする)を選びます。

デフォルトで、Kubernetes コンテナは docker service ls のようなコマンドで非表示です。この理由は、手動での(Kubernetes)管理がサポートされていないからです。これらを表示するには Show system containers (advances) (システムコンテナの表示〔高度〕)を選びます。多くの利用者には不要なオプションです。

Apply & Restart (適用と再起動)をクリックし、設定を保存します。 Kubernetes サーバをコンテナとして実行するために必要なイメージが実体化(インスタンス化)され、 kubectl.exe コマンドがパス上にインストールされます。

  • Kubernetes を有効化して実行している場合は、Docker Desktop 設定ダイアログの右横に、ステータス・バーの追加アイテムを表示します。Docker メニューの Kubernetes のステータスは、作業対象を docker-desktop と表示します。
  • Enable Kubernetes (Kubernetes 有効化)のチェックボックスをクリアしたら、Kubernetes サポートはいつでも無効にできます。無効により、この Kubernetes コンテナを停止及び削除し、 /usr/local/bin/kubectl コマンドも削除します。
  • 全てのスタックと Kubernetes リソースを削除するには、 Reset Kubernetes Cluster (Kubernetes クラスタのリセット)を選びます。
  • 他の方法で kubectl をインストールした場合は、競合が発生し、削除されます。

Docker Desktop で Kubernetes 統合機能を使う詳しい情報は、 Kubernetes 上にデプロイ を御覧ください。

リセット

Troubleshoot (トラブルシュート)のメニュー上から、 Restart Docker Desktop (Dockerデスクトップの再起動)と Reset to factory defaults (初期値にリセットする)オプションを利用できます。詳しい情報は ログとトラブルシューティング を御覧ください。

トラブルシュート

詳細は ログとトラブルシューティング ガイドを御覧ください。

Docker Desktop for Windows フォーラム(英語) にログオンしたら、コミュニティからの手助けを得たり、利用者のトピックを参照したり、議論に参加できます。

GitHub 上の Docker Desktop for Windows issues(英語) にログオンし、バグや問題の報告や、コミュニティに報告された問題を参照できます。

ドキュメントに対するフィードバックの仕方や自分で更新するには ドキュメント貢献(英語) を御覧ください。

Windows と Linux コンテナとの切り替え

Docker Desktop のメニューから、Docker CLI が通信するデーモン(Linux か Windows)を切り替えできます。 Switch to Windows containers (Windows コンテナへ切り替え)を選ぶと Windows コンテナを使います。又は、 Switch to Linux containers (Linux コンテナへ切り替え)を選ぶと Linux コンテナを使います(こちらがデフォルト)。

Windows コンテナに関する詳しい情報は、以下のドキュメントを参照ください(※リンク先はいずれも英語)。

Docker Hub

自分の Docker Hub アカウントにアクセスするには、Docker Desktop のメニューから「Sing in/Create Docker ID」(サインイン/Docker ID 作成)を選びます。一度ログインしておけば、Docker Desktop のメニューから Docker Hub リポジトリに直接アクセス可能になります。

詳しい情報は、以下の Docker Hub 記事(英語) を御覧ください。

二要素認証

Docker Desktop では、Docker Hub へのログインに二要素認証(Two-factor authentication)を有効化できます。二要素認証は Docker Hub アカウントにアクセスするとき、追加のセキュリティ段階を提供します。

Docker Hub での二要素認証を有効化する前に、Docker Desktop を通して Docker Hub アカウントにサインインする必要があります。手順は Docker Hub で二要素認証を有効にする(英語) を御覧ください。

二要素認証を有効化した後、

  1. Docker Desktop のメニューから「 Sign in / Create Docker ID 」を選択。
  2. Docker ID とパスワードを入力し、 Sign in (サインイン)をクリック。
  3. サインインに成功した後、 Docker Desktop で認証コード(authentication code)の入力を求める画面が開きます。電話に届いた6桁のコードを入力し、 Verify (確認)をクリックします。

<図>

認証に成功したら、Docker Desktop のメニューから organization やリポジトリにアクセス可能になります。

TLS 証明書の追加

Docker デーモンが、レジストリ・サーバ証明書と クライアント証明書 の検証用に、信頼できる 認証局(CA; Certificate Authorities) を追加してレジストリを認証できます。詳しい情報は FAQ にある 任意の CA 証明書を追加できますか?クライアント証明書の追加はどのように行いますか? を御覧ください。

どのようにしてカスタム CA 証明書を追加できますか?

Docker Desktop は全ての信頼できうる(ルート及び中間)証明局(CA)をサポートしています。証明書が信頼できるルート認証局や中間認証局の配下にあるかどうか、Docker は識別します。

Docker Desktop は Windows 証明局ストアに基づき、全てのユーザが信頼する CAの証明書バンドルを作成します。また、Moby の信頼できる証明書にも適用します。そのため、エンタープライズ SSL 証明書がホスト上のユーザによって信頼されている場合は、Docker Desktop からも信頼されます。

レジストリに対する CA ルート証明書のインストール方法について学ぶには、Docker エンジン記事の 証明書でリポジトリ・クライアントを認証する(英語) を御覧ください。

どのようにしてクライアント証明書を追加しますか?

自分のクライアント証明書を ~/.docker/certs.d/<MyRegistry>:<Port>/client.cert~/.docker/certs.d/<MyRegistry>:<Port>/client.key に追加できます。自分の証明書を git コマンドで送信する必要はありません。

Docker Desktop ・アプリケーションの開始時に、 Windows システム上の ~/.docker/certs.d フォルダを Moby 上(Hyper-V 上で稼働する Docker Desktop 仮想マシン)の /etc/docker/certs.d ディレクトリにコピーします。

キーチェーンに対する何らかの変更をするか、 ~/.docker/certs.d ディレクトリ内の変更を有効にするには、 Docker Desktop の再起動が必要です。

レジストリは insecure (安全ではない)レジストリとして表示されません( Docker デーモン(英語) を御覧ください )。Docker Desktop は安全ではないレジストリにある証明書を無視します。そして、クライアント証明書も送信しません。 docker run のようなレジストリから取得するコマンドは、コマンドライン上でもレジストリでもエラーになるメッセージが出ます。

認証用にクライアント TLS 証明書を設定する方法を学ぶには、Docker エンジン記事の 証明書でリポジトリ・クライアントを確認する(英語) を御覧ください。

Window に Docker Desktop をインストール

Docker Desktop for Windows は、Microsoft Windows用の Docker コミュニティ 版です。Docker Desktop for Windows は Docker Hub からダウンロードできます。

Docker Desktop のダウンロード中に、 Docker Software End User License AgreementDocker Data Processing Agreement に同意ください。

インストール前に知っておくこと

システム要件

  • Windows 10 64 ビット:Pro、Enterprise、Education(ビルド 15063 以上)
  • Hyper-V と Windows コンテナ機能の有効化が必要
  • 以下は、Windows 10 以上で Hyper-V クライアントを問題なく実行するために必要なハードウェア要件

メモ : Docker による Windows 用 Docker Desktop のサポートは、Microsoft の Windows 10 オペレーティングシステムに対するサポート・ライフサイクルに基づきます。詳細な情報は Windows ライフサイクル・ファクトシート を御覧ください。

Docker Toolbox 及び Docker Machine 利用者の方へ

Microsoft Hyper-V が Docker Desktop 実行のために必要です。Docker Desktop Windows のインストーラは、必要であれば Hyper-V を有効化し、マシンを再起動します。しかしながら、作成済みの VirtualBox VM イメージは保持し続けます。

docker-machine で作成した VirtualBox 仮想マシンは(Toolbox インストール中に、通常は default という名称の仮想マシン)、起動できなくなります。各仮想マシンは Docker Desktop と共存して利用できません。しかしながら、 docker-machine を使ってリモートの仮想マシンの削除は可能です。

インストーラに含まれるもの

Docker Desktop のインストールに含まれるのは、 Docker Engine 、 Docker CLI クライアント、 Docker ComposeNotaryKubernetesCredential Helper です。

VMware や Parralles インスタンス上で Docker Desktop を実行するような、ネストした仮想化でも動くでしょうが、無保証です。詳しい情報は ネスト対応の仮想化シナリオ を御覧ください。

メモ : Windows サーバに関する全ての Docker 互換性比較は、 Docker 互換表 を御覧ください。

Windows コンテナについて

Windows コンテナの情報をお探しですか?

  • Windows と Linux コンテナの切り替え では、Docker Desktop での Linux と Windows コンテナ間の切り替え方を説明し、上の方でチュートリアルに言及しています。
  • Getting Started with Windows Containers (Lab) では、セットアップと Windows コンテナを実行するためのチュートリアルを提供しています。対象は Windows 10、Windows Server 2016、Windows Server 2019 です。そちらでは Windows コンテナで MusicStore アプリケーションを扱う方法を説明します。
  • Windows 用 Docker コンテナ・プラットフォームについては、 Docker ウェブサイト上の 記事やブログ投稿 を御覧ください。

Windows に Docker Desktop をインストール

  1. Docker Desktop Installer.exe 」をダブルクリックし、インストーラを起動します。もしもまだインストーラ( Docker Desktop Installer.exe )をダウンロードしていなければ、 Docker Hub から取得できます。
  2. インストール・ウィザードの指示に従い、利用規約(ライセンス)を承諾し、インストーラに権限を与えてインストールを進めます。インストール途中で、Docker Desktop のインストーラに対してシステムパスワードの確認プロンプトが表示されたら、権限を与えます。ネットワーク機能のコンポーネントをインストールするには、特権アクセスが必要です。ネットワーク機能は、Docker アプリケーションと管理用 Hyper-V 仮想マシンをつなげるためです。
  3. セットアップ完了ダイアログの「 Finish 」(完了)をクリックし、Docker Desktop ・アプリケーションを起動します。

Docker Desktop を始める

インストール後の Docker Desktop は、自動的に起動できません。Docker Desktop を開始するには Docker を検索し、検索結果にある「 Docker Desktop 」を選択します。

<図>

ステータス・バーに鯨のアイコンが出続けたら、 Docker Desktop は起動・実行中であり、あらゆる端末ウインドウからアクセスできます。

<図>

もしも鯨アイコンが通知エリアから隠れている場合は、タスクバーで「上」を向いた矢印をクリックして表示します。詳しく知るには [Docker 設定] を御覧ください。

Docker Desktop アプリのインストール後は、成功のメッセージと、次のステップの提案もポップアップし、このドキュメント(英語版)のリンクを表示します。

<図>

インストールが完了したら、通知エリアにある鯨アイコンをクリックし、 About Docker Desktop (Docker Desktop について)を選び、最新版がインストールされているか確認します。

おめでとうございます! Windows 版 Docker Desktop の実行に成功しました。

Docker Desktop のアンインストール

Windows マシンから Docker Desktop をアンインストールするには、

  1. Windows の スタート メニューから、 設定 > アプリ > アプリと機能 を選びます。
  2. アプリと機能 の一覧から Docker Desktop を選択し、 アンインストール をクリックします。
  3. 選択したのを確認の後、 アンインストール をクリックします。

メモ : Docker Desktop のアンインストールは、ローカルのマシンにある Docker コンテナのイメージを破棄し、アプリケーションによって作成された全てのファイルも破棄します。

Stable と Edge バージョンの切り替え

Docker Desktop は、自分で Stable (安定版)リリースと Edge (最新)リリースを切り替え可能です。しかしながら、 Docker Desktop を一度にインストールできるのは、1つのバージョンのみ です。Stable と Edge 版のリリース切り替えるは、開発環境の安定性を損なう可能性があります。特に、新しい(Edge)チャンネルを古い(Stable)チャンネルに切り替える場合です。

例えば、 Docker Desktop の新しい Edge バージョンでコンテナを作成する場合、Stable に切り戻すと動作しなくなる可能性があります。これは、Edge の機能を使って作成したコンテナには、まだ Stable には反映されていない機能が用いられている場合があるからです。Edge コンテナで作成したり作業したりする場合には、留意し続けてください。

Edge と Stable バージョン間を安全に切り替えるには、必要に応じてイメージの保存(save)やコンテナの出力(export)を確実に行い、他のバージョンをインストールする前に、既存のバージョンをアンインストールします。詳しい情報については、以下にあるデータの保存と修復を御覧ください。

データの保存と修復

以下の手順を用いて、イメージとコンテナのデータを保存・修復できます。例えば、Edge と Stable を切り替えたいときや、仮想マシンのディスクをリセットしたいときに用います。

  1. docker save -o images.tar image1 [image2 ....] を使い、保持したい全てのイメージを保存します。Docker Engine コマンドライン・リファレンスの save セクションを御覧ください。
  2. docker export -o myContainer1.tar container を使い、保持したい全てのコンテナをエクスポート(出力)します。Docker Engine コマンドライン・リファレンスの export セクションを御覧ください。
  3. 現在のバージョンの Docker Desktop をアンインストールし、異なるバージョン(Stable 又は Edge)をインストールし、仮想マシン・ディスクをリセットします。
  4. docker load -i images.tar を使い、以前に保存したイメージを再読み込みします。Docker Engine の load を御覧ください。
  5. docker import -i myContainer1.tar を使い、以前にエクスポートしたコンテナに対応するファイルシステム・イメージを作成します。Docker Engine の import を御覧ください。

データ・ボリュームのバックアップと修復の仕方に関する情報は、 Backup, restore, or migrate data volumes を御覧ください。

Docker Desktop ・ダッシュボード

Docker Desktop のダッシュボードは、コンテナやアプリケーションの操作や、マシン上のアプリケーションのライフサイクルを直接管理するための、シンプルなインターフェースを提供します。ダッシュボードのユーザ・インターフェースで、実行中や停止中の前コンテナの稼働状態や、実行中であればその状態を表示します。直感的なインターフェースを通して、コンテナを含む Docker オブジェクトと Docker Compose ベースのアプリケーションに対し、調査、アクション、管理するために共通する処理を行います

Docker Desktop ・ダッシュボードは、以下の利点を提供します。

  • GUI は CLI がもたらすコアな情報を抽象化します
  • コンテナの挙動を検索・調査をするために、UI を通してコンテナのログに直接アクセスします
  • Compose アプリケーションを理解するために、 UI を通して連結された Compose ログにアクセスします
  • コンテナによって使用しているポートを、素早く見えるようにします
  • コンテナのリソース使用状況を監視します

加えて、ダッシュボード UI を使って、以下のことを可能にします。

Docker Desktop のダッシュボードにアクセスするには、Docker メニューから Dashboard (ダッシュボード)を選択します。ダッシュボードは、全てのコンテナとアプリケーションの一覧を提供します。

<図>

実行中のコンテナとアプリケーションの探索

Docker メニューから、 Dashboard を選択します。ここでは実行中のコンテナとアプリケーションの全リストを表示します。Docker Desktop ・ダッシュボード上に表示されているのは、実行中のコンテナとアプリケーションのみなので御注意ください。

Redis コンテナの開始

Redis コンテナを開始するには、任意の CLI を開き、以下のコマンドを実行します。

docker run -dt redis

これは、新しい Redis コンテナを作成します。Docker メニューから Dashboard を選択し、新しい Redis コンテナを表示します。

<図>

サンプル・アプリケションの開始

それでは、サンプル・アプリケーションを実行しましょう。Docker サンプル・ページから サンプル投票アプリ をダウンロードできます。サンプル投票アプリは、複数の Docker コンテナを横断する分散アプリケーションです。

<図>

サンプル投票アプリケーションの含むもの:

  • PythonASP.NET Core によるフロントエンド・ウェブ・アプリケーションを通して、2つの選択肢から投票できます
  • Redis 又は NATS キューは、新しい投票を集めます
  • .NET CoreJava.NET Core 2.1 ワーカーは、投票を取り込み保存します
  • Docker ボリューム上の、PostgresTiDB データベース
  • Node.jsASP.NET Core SignalR ウェブアプリは、投票結果をリアルタイムで表示します。

アプリケーションを開始するには、CLI でサンプル投票アプリケーションを含むディレクトリに移動し、 docker-compose up --build を実行します。

$ docker-compose up --build
Creating network "example-voting-app-master_front-tier" with the default driver
Creating network "example-voting-app-master_back-tier" with the default driver
Creating volume "example-voting-app-master_db-data" with default driver
Building vote
Step 1/7 : FROM python:2.7-alpine
2.7-alpine: Pulling from library/python
Digest: sha256:d2cc8451e799d4a75819661329ea6e0d3e13b3dadd56420e25fcb8601ff6ba49
Status: Downloaded newer image for python:2.7-alpine
 ---> 1bf48bb21060
Step 2/7 : WORKDIR /app
 ---> Running in 7a6a0c9d8b61
Removing intermediate container 7a6a0c9d8b61
 ---> b1242f3c6d0c
Step 3/7 : ADD requirements.txt /app/requirements.txt
 ---> 0f5d69b65243
Step 4/7 : RUN pip install -r requirements.txt
 ---> Running in 92788dc9d682

...
Successfully built 69da1319c6ce
Successfully tagged example-voting-app-master_worker:latest
Creating example-voting-app-master_vote_1   ... done
Creating example-voting-app-master_result_1 ... done
Creating db                                 ... done
Creating redis                              ... done
Creating example-voting-app-master_worker_1 ... done
Attaching to db, redis, example-voting-app-master_result_1, example-voting-app-master_vote_1, example-voting-app-master_worker_1
...

アプリケーションの実行に成功したら、 Docker メニューから Dashboard を選択し、サンプル投票アプリケーションを見ましょう。アプリケーションを展開し、アプリケーション内で実行中のコンテナを見ます。

<図>

これで、ダッシュボード上で実行中のコンテナとアプリケーションの一覧が見られます。それでは、何ができるか見ていきましょう。

  • Port をクリックし、コンテナによって公開されているポートをブラウザで開きます
  • CLI をクリックし、コンテナ上にターミナルを開き、コマンドを実行します
  • StopStartRestartDelete をクリックし、コンテナのライフサイクルを処理します

Search オプションを使い、特定のオブジェクトを検索します。また、様々なオプションでコンテナやアプリケーションを並び替えできます。 Sort by ドロップ・ダウンで、利用可能なオプションの一覧を表示します。

コンテナやアプリケーションの操作

Docker Desktop ・ダッシュボードから、先ほど起動したサンプル投票アプリケーションを選択します。

application view 一覧から、実行している全アプリケーションのコンテナ一覧と、詳細なログ表示を行います。また、アプリケーションの起動、停止、削除も行えます。

コンテナ名の上にマウスを移動すると、主要な操作可能な機能を表示します。特定のイベントに対するアプリケーションのログを検索するには、下の方にある Search オプションを使います。あるいは、クリップボードにログをコピーするには Copy を選択します。

<図>

特定のコンテナに対する詳細情報を指定するには、クリックします。 container view には LogsInspectStats タブが表示され、ボタンのクリックで様々なアクションを処理できます。

<図>

  • Logs を選択し、コンテナからのログを表示します。また、任意のイベントをログから検索したり、クリップボードにログをコピーしたりできます。
  • Inspect を選択し、コンテナに対するローレベルな情報を表示します。また、ローカルのパスや、イメージのバージョン番号、 SHA-256 、ポート割り当て(マッピング)、その他詳細を確認できます。
  • Stats をクリックし、コンテナのリソース使用率に関する情報を表示します。コンテナによって、たくさんの CPU 、ディスクI/O 、メモリ、ネットワーク I/O が使われているのが見えます。

また、トップバー上にある quick action(クイック・アクション)ボタンを使っても、CLI を開いてコンテナ内でコマンドを実行するような共通操作を行えます。また、コンテナに対する停止、起動、再起動、削除のようなライフサイクルの操作も行えます。

Port をクリックし、コンテナが公開(露出)しているポートをブラウザで開きます。

<図>

フィードバック

新しいダッシュボードのユーザーインターフェースについて、皆さんから伺いたいです。あなたのフィードバックをお知らせいただくには、 docker/for-win GitHub リポジトリで issue を作成ください。

Kubernetes 上にデプロイ

Docker デスクチップはスタンドアロン Kubernetes サーバとクライアントを含むだけでなく、Docker コマンドライン・インターフェースと統合しています。 Kubernetes サーバはローカルの Docker インスタンス内で実行します。設定の変更はできず、単一ノードのクラスタです。

ローカルシステム上の Docker コンテナ内で Kubernetes サーバが稼働します。また、用途はローカルでのテストのみです。Kubernetes サポートを有効化したら、Kubernetes 、 Swarm 、そしてスタンドアロン・コンテナを、それぞれ並列にワークロードをデプロイ可能となります。

Kubernetes を有効化し、 Kubernetes 上にワークロードをデプロイするテストを開始するには、 Docker Desktop for Windows > Getting started を御覧ください。

Docker コマンドを使う

docker stack deploydocker-compose.yml ファイルとスタック名を使い、Kubernetes 上にスタックをデプロイ可能です。

docker stack deploy --compose-file /path/to/docker-compose.yml mystack
docker stack services mystack

デプロイしたサービスは kubectl get services コマンドで表示できます。

namespace(名前空間)の指定

デフォルトでは default namespace (名前空間)が使われます。名前空間は --namespace フラグで指定します。

docker stack deploy --namespace my-app --compose-file /path/to/docker-compose.yml mystack

kubectl get services -n my-app の実行は、 my-app 名前空間にデプロイしているサービスのみ表示します。

デフォルトのオーケストレータを上書き

Kubernetes でテストをしながら、複数のワークロードを swarm モードにデプロイしたい場合があるでしょう。 DOCKER_STACK_ORCHESTRATOR 環境変数を使い、操作中のターミナル・セッションや単一の Docker コマンドで、デフォルトのオーケストレータを上書きします。この環境変数は 設定されていない (デフォルト、この場合はオーケストレータが Kubernetes)か、 swarm 又は kubernetes をセットします。以下はコマンドを実行する前に環境変数を設定し、単一デプロイメント用のオーケストレータを上書きするコマンドです。

set DOCKER_STACK_ORCHESTRATOR=swarm
docker stack deploy --compose-file /path/to/docker-compose.yml mystack

あるいは、デプロイメント向けのデフォルト・オーケストレータをデプロイ時に上書きする場合は、 --orchestrator フラグでも設定できます。

docker stack deploy --orchestrator swarm --compose-file /path/to/docker-compose.yml mystack

メモ : Kubernetes と swarm モードで同じアプリをデプロイすると、ポートやサービス名に競合を引き起こす場合があります。

kubectl コマンドを使う

Windows Kubernetes 統合機能により、Kubernetes CLI コマンドが C:\>Program Files\Docker\Docker\Resources\bin\kubectl.exe に提供されています。この場所はシェルの PATH 変数に入っていない場合があるため、コマンドはフルパスで実行するか、 PATH に追加する必要があります。 kubectl に関する情報は、 公式 kubectl ドキュメント を御覧ください。コマンドのテストは、利用可能なノード一覧の表示で行えます。

kubectl get nodes

NAME                 STATUS    ROLES     AGE       VERSION
docker-for-desktop   Ready     master    3h        v1.8.2

サンプル・アプリケーション

Docker は以下のデモ用アプリケーションを作成しました。 docker stack deploy コマンドを使って swarm モードや Kubernetes にデプロイできます。

version: '3.3'

services:
  web:
    image: dockersamples/k8s-wordsmith-web
    ports:
     - "80:80"

  words:
    image: dockersamples/k8s-wordsmith-api
    deploy:
      replicas: 5
      endpoint_mode: dnsrr
      resources:
        limits:
          memory: 50M
        reservations:
          memory: 50M

  db:
    image: dockersamples/k8s-wordsmith-db

既に Kubernetes YAML ファイルがある場合は、 kubectl コマンドを使ってデプロイできます。

Docker Desktop for Windows のネットワーク構築機能

Docker Desktop は、簡単に利用できるようにする複数のネットワーキング機能を提供します。

機能

VPN パススルー

Docker Desktop のネットワーク構築は、VPN 接続時も動作します。そのためには、あたかも Docker アプリケーションが発信しているかのように、Docker Desktop がコンテナからのトラフィックを取り込み、Windows へ投入します。

ポートマッピング

コンテナに -p 引数を付けて実行します。こちらが実行例です。

$ docker run -p 80:80 -d nginx

Docker Desktop はコンテナ内のポート 80 で実行しているものが何であろうと(この例では nginx )、 localhost のポート 80 上で利用可能にします。ホスト側で異なるポートを指定するにはどうしたら良いでしょうか。例えば、ホストマシン側でポート 80 上で実行中の何かがある場合、コンテナに対しては別のポートで接続できます。

$ docker run -p 8000:80 -d nginx

これで localhost:8000 への接続が、コンテナ内のポート 80 へ送られます。 -p の構文は ホスト側ポート:クライアント側ポート です。

HTTP/HTTPS プロキシ・セットアップ

プロキシ を御覧ください。

既知の制限、利用例、回避方法

以下で扱うのは、 Docker Desktop for Windows 上のネットワーク構築スタックにおける、現時点での制限の要約と、回避策に対する考え方です。

Windows には docker0 ブリッジがありません

ネットワーク構築機能の実装が、Docker Desktop for Windows 用のため、ホスト側では docker0 インターフェースは見えません。このインターフェースは、実際には仮想マシン内にあります。

コンテナに ping できません

Docker Desktop for Windows は Linux コンテナに対してトラフィックを経路付け(ルーティング)できません。一方で、Windows コンテナに対しては ping ができます。

コンテナごとに IP アドレスを割り当てられません

docker (Linux) ブリッジ・ネットワークは Windows ホストから到達できません。一方で、Windows コンテナでは動作します。

利用例と回避方法

前述の制限に対応する、2つのシナリオがあります。

コンテナからホスト上のサービスに対して接続したい

ホストの IP アドレスは変動します(あるいは、ネットワークへの接続がありません)。18.03 よりも前は、特定の DNS 名 host.docker.internal での接続を推奨していました。これはホスト上で内部の IP アドレスで名前解決します。これは開発用途であり、Docker Desktop for Windows 外の本番環境では動作しません。

また、ゲートウェイに対しては gateway.docker.internal で到達可能です。

Windows からコンテナに対して接続したい

localhost に対するポート転送(port forwarding)が動作します。つまり、 --publish-p-P が全て機能します。Linux からのポート公開(露出)は、ホスト側に転送されます。

現時点で推奨するのは、ポートの公開か、他のコンテナからの接続です。これは Linux 上でも同様ですが、ブリッジ・ネットワークではなくオーバレイ・ネットワーク上にコンテナがある場合、到達(経路付け)できません。

始めましょう で用いた例にある nginx ウェブサーバを表示するには、次のコマンドを使います。

$ docker run -d -p 80:80 --name webserver nginx

構文を明確にしましょう。以下の2つのコマンドは、いずれも同じコンテナのポート 80 をホスト側のポート 8080 に公開するものです。

$ docker run --publish 8000:80 --name webserver nginx

$ docker run -p 8000:80 --name webserver nginx

全ポートを公開するには -P フラグを使います。例えば、以下のコマンドはコンテナを起動し(デタッチド・モードで)、 -P フラグはコンテナが公開する全てのポートを、ホスト側ランダムなポートに対して割り当てます。

$ docker run -d -P --name webserver nginx

docker run で公開するオプションに関する詳細は run コマンドを御覧ください。

Docker Toolbox の移行

このページで説明するのは、Docker Toolbox ディスクイメージや既にあるイメージを Docker Desktop for Windows に移行する方法です。

Docker Toolbox ディスクイメージを Docker Desktop への移行方法

警告 : Docker Toolbox からのディスクイメージ移行は、既存の Docker イメージを上書きします。移行手順では、以前の Docker Toolbox データ全体を含む仮想マシン全体を置き換えます。

  1. qemu をインストールします。 https://cloudbase.it/downloads/qemu-img-win-x64-2_3_0.zip
  2. Docker Desktop for Windows をインストールします。
  3. もしも Docker が起動中であれば停止します。
  4. 現在の Docker 仮想マシン・ディスクを安全な場所の移動します。
mv 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx' C:/<any directory>

5. Toolbox ディスク・イメージを変換します。

qemu-img.exe convert 'C:\Users\<username>\.docker\machine\machines\default\disk.vmdk' -O vhdx -o subformat=dynamic -p 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MobyLinuxVM.vhdx'

6. Docker Desktop を(変換したディスクを用いて)再起動します。

Docker Toolbox をアンインストールする方法

Docker Toolbox イメージを移行するかどうかに関わらず、アンインストールを決めるべきでしょう。Toolbox をクリーン・アンインストールする詳細は、 How to uninstall Toolbox を御覧ください。

ログとトラブルシューティング

このページに含む情報は、どのようにして原因を追及し、問題を解決し、ログを送信し、Docker Desktop のチームとやりとりし、フォーラムやナレッジ・ハブで使ったり、GitHub 上で問題を見たり記録したり、既知の問題に対する回避策を発見する方法です。

トラブルシュート

メニューバーにある Docker のアイコン > Troubleshoot を選択肢、トラブルシュートのオプションを表示します。

<図>

トラブルシュートのページには、以下のオプションを含みます。

  • Restart Docker Desktop (Docker Desktop の再起動): 選択すると、Docker Desktop を再起動します。
  • Run Diagnostics (診断の開始): このオプションを選択すると、Docker Desktop 上のあらゆる問題を診断します。診断に関する詳細情報は、 問題の診断、フィードバック送信、GitHub issue の作成 を御覧ください。
  • Reset Kubernetes cluster (Kubernetes クラスタのリセット): このオプションを選択すると、全てのスタックと Kubernetes リソースを削除します。詳しい情報は [Kubernetes] を御覧ください。
  • Reset to factory defaults (初期値のデフォルトにリセット): このオプションを選択すると、Docker Desktop の全てのオプションを初期値にリセットし、Docker Desktop が始めてインストールされたのと同じ状態にします。

問題の診断、フィードバック送信、GItHub issue の作成

アプリ内診断

発生した問題が、このページ内のドキュメントで解決できない場合は、 GitHub の Docker Desktop for Windows issuesDocker Desktop for Windows forum で、ログデータのトラブルシュートを手助けできるかもしれません。

メニューの Docker アイコン > Troubleshoot を選択します。

<図>

Diagnose & Feedback ウインドウが開始されたら、診断情報の収集が始まります。診断情報が取得可能であれば、アップロードするときに必要となる Diagnostic ID を得られます。これは Docker チームとやりとりするときに必須です。私たちの個人データ取り扱いポリシーに関する情報は how is personal data handled in Docker Desktop を御覧ください。

<図>

Report an issue (問題を報告)をクリックすると GitHub 上の Docker Desktop for Windows issues をウェブブラウザで開き、送信前に必要な一式が揃った "New issue" テンプレートが適用されます。その際に Diagnostic ID (診断 ID)の添付を忘れないでください。

<図>

ターミナルから診断

例えば Docker Desktop for Windows が開始できないなど、場合によっては自分での診断実行が役立つ場合もあります。

まず com.docker.diagnose を探します。大抵は C:\Program Files\Docker\Docker\resources\com.docker.diagnose.exe
にあるでしょう。

Powershell で診断の作成とアップロードをするには、次のように実行します。

 PS C:\> & "C:\Program Files\Docker\Docker\resources\com.docker.diagnose.exe" gather -upload

診断が完了したら、次のように診断 ID を含む出力結果が得られます。

Diagnostics Bundle: C:\Users\User\AppData\Local\Temp\CD6CF862-9CBD-4007-9C2F-5FBE0572BBC2\20180720152545.zip
Diagnostics ID:     CD6CF862-9CBD-4007-9C2F-5FBE0572BBC2/20180720152545 (uploaded)

トラブルシューティングのトピック

証明書の正しいセットアップを確実にする

Docker Desktop は安全ではないレジストリ(insecure registry)上にある証明書を無視します。また、そちらに対してクライアント証明書も送りません。 docker run のようなコマンドでは、レジストリからの取得(pull)を試みても、次のようなコマンドライン上のエラーメッセージを表示します。

Error response from daemon: Get http://192.168.203.139:5858/v2/: malformed HTTP response "\x15\x03\x01\x00\x02\x02"

レジストリ側でも同様にエラーが出ます。こちらが例です。

2017/06/20 18:15:30 http: TLS handshake error from 192.168.203.139:52882: tls: client didn't provide a certificate
2017/06/20 18:15:30 http: TLS handshake error from 192.168.203.139:52883: tls: first record does not look like a TLS handshake

クライアントとサーバ側証明書の使用に関しては、導入ガイドのトピックにある 任意の CA 証明書を追加するには 、及び、 クライアント証明書を追加するには を御覧ください。

ボリューム

共有ボリュームにおける、データ・ディレクトリ上の権限(permission)エラー

Docker Desktop は 共有ボリューム 上の権限(パーミッション)をデフォルトで 0777ユーザ 及び グループ に対して、 読み込み書き込み実行 の権限)に設定します。

共有ボリューム上におけるデフォルトの権限は、変更できません。もしも、アプリケーションの動作上、デフォルトの共有ボリューム上でコンテナ実行時に異なる権限が必要となる場合は、ホストをマウントしないボリュームを使用するか、アプリケーション側が初期設定の権限で動作する設定を見つける必要があります。

現時点における Docker Desktop の実装では、ホストをマウントするボリュームは マイクロソフト SMB プロトコル をベースにしているため、権限を制御する chmod のようなキメ細かなサポートはありません。

また、 FAQ の コンテナのデプロイごとに、必要に応じて共有ボリューム上の権限を変更できますか をご覧いただき、詳しい情報は 御覧 issue の Controlling を御覧ください。

共有ドライブ上で inotify が動作しません

現時点では、 inotify は Docker Desktop 上で動作しません。これが明らかになる例は、アプリケーションがコンテナがマウントしたドライブに対する読み書きが必要な場合です。ファイルシステム上の inotify に頼らず、私たちが推奨するのはフレームワークやプログラミング言語にあるポーリング(polling)機能の使用です。

共有ドライブ上へのボリューム・マウントが Linux コンテナに必要です

マウント・ボリュームを使用中に、アプリケーション・ファイルが見つからないというランタイム・エラーが表示される場合は、ボリューム・マウントに対するアクセスが拒否されているか、あるいは、 Docker Compose などを使っていてサービスが開始できない場合には、 共有ドライブ の有効化が必要でしょう。

Linux コンテナ(Windows コンテナではありません)でボリュームをマウントするには、共有ドライブが必要です。Docker アイコンをクリックし、それから Settings > Shared Drives を選び、Dockerfile と ボリュームを置くためのドライブを共有します。

共有ドライブ(ボリューム)に対してドメインのユーザが権限を持っているかどうか確認

Tip : 共有ドライブが必要になるのは [Linux コンテナ]のボリューム・マウントであり、Windows コンテナでは必要ありません。

共有ドライブに対するアクセス権限は、セットアップをした共有ドライブを使っているユーザ名とパスワードで試みます。もしも共有ドライブをセットアップしたユーザ名と異なるユーザ名で docker コマンドを実行しようとしても、マウントしたボリュームに対するアクセス権限はありません。ボリュームは空になって見えます。

この解決方法は、ドメインのユーザ・アカウントを切り替え、共有ドライブ上の資格情報(クレデンシャル)をリセットします。

以下はこの問題に対処するデバッグ例です。 c ドライブをドメインユーザではなくローカルユーザで共有した場合を考えましょう。ローカルユーザは samstevens 、ドメインユーザは merlin と仮定します。

  1. Windows ドメインユーザ(この例では merlin )でログインしているかどうかを確認します。
  2. net share c を実行し、 <ホスト名>\<ユーザ名>, FULL でユーザ権限を見ます。
> net share c

Share name        C
Path              C:\
Remark
Maximum users     No limit
Users             SAMSTEVENS
Caching           Caching disabled
Permission        windowsbox\samstevens, FULL

3. 共有を解除するため、以下のコマンドを実行します。

> net share c /delete

4. 共有ドライブのダイアログ を通して、ドライブを再共有し、Windows ドメインユーザ・アカウントの資格情報(クレデンシャル)を与えます。
5. net share c を再度実行します。

> net share c

Share name        C
Path              C:\
Remark
Maximum users     No limit
Users             MERLIN
Caching           Caching disabled
Permission        windowsbox\merlin, FULL

関連項目として、GitHub 上の issue に マウントしたボリュームが、コンテナから空になった(英語) があります。

nobrl オプションを使うホスト上のパスをボリューム・マウントすると、データベースのロックを上書きする

ホスト上のボリューム・マウントを使用すると、データベース・ソフトウェアやオプションの有効化によっては、思いがけない問題に遭遇しがちです。Docker Desktop for Windows はホスト上のパスをマウントするのに SMB/CIFS プロトコル(英語) を使用し、そこを nobrl オプションでマウントしますが、データベース・サーバがロック要求を送信するのを阻害します(docker/for-win#11docker/for-win#694 )。これが確実に発生するのは、ホスト上で共有されているデータベースファイルにコンテナがアクセスするときです。たとえ、ネットワーク越しのデータベース接続問題が解決したとしても、この「アンロック」されていない側面が、データベースの機能性を妨げます(例えば、SQLite の WAL については docker/for-win#1886 に記述)。

可能であれば、ホスト上のネットワーク・パスを共有ドライブとしてボリューム・マウントするのを避け、そのかわりに MobyVM 上をマウントするか、 データ・ボリューム(英語)(名前付きボリューム)か データ・コンテナ(英語) を作成します。
また、Compose ファイル・ドキュメントの service 設定かの volume キー(英語)ボリューム設定リファレンス(英語) も御覧ください。

ローカルセキュリティポリシーが共有ドライブをブロックし、ログインエラーを発生させます

Docker Desktop for Windows 共有ドライブ が用いる共有ドライブのマウントには、権限が必要です

もしもローカルポリシーが妨げる場合、Docker 上で共有ドライブを有効化しようとしてもエラーになるでしょう。これは Docker 側では解決できないため、この機能を使うための権限が必要です。

こちらはエラーメッセージ例を切り取ったものです。

Logon failure: the user has not been granted the requested logon type at
this computer.

[19:53:26.900][SambaShare     ][Error  ] Unable to mount C drive: mount
error(5): I/O error Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
mount: mounting //10.0.75.1/C on /c failed: Invalid argument

Docker for Windows issue #98(英語) も御覧ください。

symlinks の制限を理解する

コンテナ間で symlinks は動作します。しかし、コンテナの外で作成した symlinks (例えばホスト上)は動作しません。詳しく学ぶには、 FAQ の symlinks をサポートしますか? を御覧ください。

予期しない構文エラー(unexpected syntax error)を避けるため、コンテナ内でファイルの行末を unix 風にする

コンテナ内で実行するあらゆるファイルは、 Unix 風の行末 \n を使う必要があります。これをファイルに含むのは、ビルド用のコマンドラインや Dockerfile における RUN 命令で参照するからです。

Docker コンテナと docker build の実行は Unix 環境のため、コンテナ内のファイルは Unix 風の行末 \n を使うのが必須です。 Window 風の \r\n ではありません。シェルスクリプトのようなファイルを作成するときは、Windows ツールを使うとデフォルトで Windows 風の行末になるので、気に留めておいてください。各コマンドは、最終的には Unix をベースするコンテナ内の Unix コマンドに渡されます(例えば、シェルスクリプトは /bin/sh に渡されます)。もしも Windows 風の行末が用いられると、 docker run は構文エラーになり失敗します。

この問題と解決方法の例は、GitHub 上の issue を御覧ください: Docker RUN でシェルスクリプトの実行に失敗する(英語)

仮想化

Docker Desktop を正しく機能するには、マシンには以下の機能が必要です。

  1. Hyper-V をインストールして、動作させる
  2. 仮想化の有効化
Hyper-V

Docker Desktop をインストールして有効化するには、 Hyper-V と同様に Windows Powershell 用 Hyper-V モジュールも必要です。Docker Desktop インストーラは、これらを有効化します。

また、Docker Desktop は Hyper-V を使うために2つの CPU 機能を使います。すなわち、仮想化と Rapid Virtualization Indexing (RVI) とも呼ばれる Second Level Address Translation (SLAT) です。同じシステムの BIOS 上で、Virtualization (仮想化)の有効化が必須です。必要な手順はベンダによって異なりマスが、典型的な BIOS オプションは Virtualization Technology (VTx) と呼ばれるものか、似たようなものです。Hyper-V 機能が必要とする全てを確認するには、 systeminfo コマンドを実行します。詳細は Windows 10 Hyper-V のシステム要件 を御覧ください。

Hyper-V を主導でインストールするには、Windows 10 上に Hyper-V をインストールする を御覧ください。インストール後は再起動が必用です。Hyper-V をインストールしても再起動をしないと、 Docker Desktop は正しく動作しません。

スタートメニューから、 Windows 機能の有効化又は無効化 を入力し、エンターを押します。以下の画面のようになっていると、Hyper-V は有効です。

<図>

Docker Machine 用の Hyper-V ドライバ

Docker Desktop のインストールには、Docker Machine という以前のツールが使う古い boot2docker.iso と、ローカルで仮想マシンを作成するための Microsoft Hyper-V ドライバ を含みます。これらは Docker Desktop とはほとんど関係がありませんが、Docker Machine で複数のローカル仮想マシン(VM)を作成したいときや、リモートマシンをプロビジョン(自動構築)するために必要です。詳しくは Docker Machine の記事を御覧ください。こちらのドキュメントは Docker Machine on Windows について探している方向けのドキュメントであり、必要となる Hyper-V の有効化や、アクティブに切り替える外部ネットワークや、 前述の Docker Machine ドライバ例 にある docker-machine create コマンドのフラグも含むリファレンスです。

仮想化を必ず有効化

Hyper-V を追加するには、仮想化の有効化が必要です。タスクマネージャー上のパフォーマンス・タブをクリックします。

<図>

もしも Hyper-V を手動でアンインストールするか、仮想化を無効にしたら、Docker Desktop は起動できません。 Windows 10 Enterprise では Docker for Windows を実行できません(英語) を御覧ください。

Docker Desktop for Windows インストール後のネットワーク機能と WiFi 問題

Docker Desktop のインストールと起動によって、何人かの利用者は、ネットワーク機能の問題が発生する可能性があります。例えば、インストールあるいは自動再起動の後、ネットワーク・アダプタと WiFi のどちらかか両方が無効化するものです。問題のいくつかの原因は、 VirtualBox を導入しているか、そのネットワーク・アダプタをインストールしている場合ですが、その他の原因によっても起こる可能性があります。GitHub issue Hyper-V 機能の有効化で wi-fi が切れる(英語) を御覧ください。

こちらは、もしも似たような問題が発生したときの対応手順です。

  1. 仮想化を必ず有効化 で前述した通り、 仮想化 の有効化を確認します。
  2. Hyper-V を必ず有効化 で前述した通り、Hyper-V のインストールと有効化を確認します。
  3. Hyper-V マネージャー の右側にある 操作 タブ上の 仮想スイッチマネージャーDockerNAT の有効化を確認します。 <図>
  4. 外部ネットワークスイッチをセットアップします。Docker Machine で複数のローカル VM のセットアップを検討中であれば、前述の Docker Machine 用 Hyper-V ドライバ にある作業はいずれ必要です。 DockerNAT はこのスイッチに置き換え可能です。
  5. 以上の手順でも問題解決できない場合は、次の クリーンアップ Readme にある手順を進めてください。

Windows クリーンアップスクリプトを実行する前に、必ずお読みください
クリーンアップ・コマンドには2つのフラグ -Cleanup-ForceDeleteAllSwitches があります。スクリプトの実行前に各ページをお読みください。特に -ForceDeleteAllSwitches に書かれた警告をお読みください。

Windows コンテナと Windows サーバー

Windows サーバー上での Docker Desktop はサポート外です。そのかわり、追加費用なしで Docker Enterprise Basic を利用可能です。

Windows 10 上で Windows コンテナの実行に関する疑問があれば、 Windows と Linux コンテナ間の切り替え を御覧ください。

docker/labsGetting Started with Windows Container に全てのチュートリアルがあります。

ネイティブな Windows バイナリをインストールしたら、Windows Desktop がなくても Windows コンテナの開発と実行が可能です。しかし、この方法で Docker をインストールしたら、Linux コンテナの開発と実行ができません。もしもネイティブな Docker デーモンで Linux コンテナの実行を試みても、次のようなエラーが発生します。

C:\Program Files\Docker\docker.exe:
 image operating system "linux" cannot be used on this platform.
 See 'C:\Program Files\Docker\docker.exe run --help'.

localhost の Windows コンテナの制限と公開ポート

Docker Desktop for Windows は、Windows と Linux コンテナの切り替えオプションがあります。もし Windows コンテナを使っている場合は、現時点における Windows NAT (WinNAT) の実装により、ネットワーク機能に対する複数の制限があります。それぞれの制限は Windows コンテナ・プロジェクトの進化によって、いずれは解決する可能性があります。

Windows 10 1819 で使える Docker Desktop for Windows から、Windows コンテナはローカルホスト上でのポート公開が可能になりました。Windows Server 2019 / 1809 で Docker EE を使う場合も同様です。

もしも Windows 10 18.09 未満のバージョンを使う場合は、Windows コンテナの公開ポートがローカルホストにループバックされる問題があります。ホストからコンテナのエンドポイントに到達できる唯一の方法は、コンテナの IP とポートを使います。 Windows 10 18.09 では、コンテナはローカルホスト上にポートを公開可能です。

それでは、Docker を使ってイメージを取得してウェブサーバを実行するため、次のようなコマンド実行例を見ましょう。

> docker run -d -p 80:80 --name webserver nginx

curl http://localhost を使うか、ウェブ・ブラウザで http://localhost を表示しても、 nginx ウェブページは(Linux コンテナの場合とは違い)表示されません。

ローカルホストから Windows コンテナに到達するには、サービスを実行しているコンテナの IP アドレスとポートを指定する必要があります。

コンテナに割り当てられている IP アドレスを知るには、 docker inspect に複数の --format オプションと、コンテナの ID 又は名前を使います。先ほどの例では、コマンドを実行するときにコンテナ ID ではなくコンテナ名( webserver )を使います。

$ docker inspect \
  --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
  webserver

これにより、コンテナの IP アドレスを次のように表示します。

$ docker inspect \
  --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
  webserver

172.17.0.2

あとは、ウェブサーバに対して http://172.17.0.2:80 を使って接続できるようになります(あるいは、ポート 80 はデフォルトの HTTP ポートのため、シンプルに http://172.17.0.2 を使います)。

更に詳しい情報は、以下を御覧ください。

ネストした仮想化環境で Docker Desktop を実行

Paralles や VMware Fusion a Mac 上で動く Windows 10 仮想マシン内で、適切な設定をすると Docker Desktop を実行可能です。しかしながら、ハードウェア仮想化アプリの手法によって、問題や一時的な問題が発生する可能性があります。そのため、 Docker Desktop はネストした仮想化環境での実行をサポートしません 。動く場合もあれば、動かない場合もあります。

裁量の結果を出すには、Windows システム上で Docker Desktop をネイティブに実行するのを推奨します(Windows コンテナも Linux コンテナも動作します)。また Mac では Linux コンテナのみ動作します。

それでもネスト化した仮想化環境を使いたい場合には
  • VMware や Paralles でネスト化した仮想化サポートが有効になっているかどうかを確認します。設定の Hardware > CPU & Memory > Advanced Options > Enable nested virtualization を確認します(展開するメニュー順番は、若干変わるかもしれません)。
  • 仮想マシンが最小 2 CPU と、ワークロードを実行するための十分なメモリを使うように設定します。
  • システムは多少のアイドル(余裕)があるようにします。
  • Windows OS を最新版へ確実に更新します。insider ビルドによっては、複数の問題があります。
  • 適切なプロセッサも必要です。例えば、Westmere ベースの Mac Pro は、Nehalem ベースの Mac Pro よりもハードウェア仮想化機能が追加されていますし、更に新しい世代のインテル・プロセッサもそうでしょう。
ネスト化した仮想化環境で起こる典型的な問題
  • Linux 仮想マシンのブート時に確認します。ログを見て、 Moby を先頭に含む行がないかどうか調べます。実在のハードウェアでは、Linux 仮想マシンのブートにかかる時間は 5 ~ 10 秒です。つまり、おおよその時間は、 Connected のログ記録から * Starting Docker ... [OK] ログ記録までです。もしも Windows 仮想マシン内で Linux 仮想マシンをブートするのであれば、この処理にかかる時間はより長くなります。タイムアウトは 60 秒以上です。もし VM が時間までに起動しなければ、リトライします。リトライに失敗したら、エラーを表示します。Windows 仮想マシンに対し、更にリソースを提供することで回避可能な場合があります。
  • ブート時、タイムスタンプ・カウンタ(TSC)の補正を Linux が行うとき、仮想マシンが落ちる場合があります。この処理はタイミングがセンシティブなため、仮想マシン内で仮想マシンを実行する場合に落ちるかもしれません。また、 CPU 使用率も高くなります。
  • Paralles on Mac では "PMU Virtualizatoin" が無効かどうかを確認します。 設定の Hardware > CPU & Memory > Advanced Settings > PMU Virtualization を確認します。
関連する問題。

GitHub の議論スレッドは Docker for Windows issue 267 です。

ネットワーク機能の課題

Docker Desktop 安定版(stable)を使っているユーザ数名から、 Docker Hub への接続問題が報告されています。(GItHub issue 22567 を御覧ください)

以下はコマンドとエラーメッセージの例です。

> docker run hello-world

Unable to find image 'hello-world:latest' locally
Pulling repository docker.io/library/hello-world
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error while pulling image: Get https://index.docker.io/v1/repositories/library/hello-world/images: dial tcp: lookup index.docker.io on 10.0.75.1:53: no such host.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.

この問題を一時的に回避するには、 DNS サーバの設定をリセットし、 Google DNS の固定アドレス 8.8.8.8 を使います。この設定は Settings から行えます。

Network ダイアログについては、 ネットワーク のトピックに詳細があります。この設定を適用したら、少し時間をおいた後、Docker は自動的に再起動します。

NAT/IP 設定

デフォルトでは、 Docker Desktop は 10.0.75.0/24 の内部ネットワーク・プリフィックスを使用します。通常のネットワークセットアップで衝突してしまう場合には、 Settings (設定)メニューからプリフィックスを変更可能です。 設定 以下の ネットワーク 記事を御覧ください。

回避策(ワークアラウンド)

現時点で inotify が Docker Desktop では機能しません

もしも Node.jsnodemon を使っているのであれば、こちらで説明しているフォールバック・プーリング・モードを試すのが、一時的な回避策です: nodemon が node アプリケーションを再起動しません(英語) 。また、GitHub issue の 共有ドライブの inotify が動作しません(英語) も御覧ください。

再起動

PC を再起動し、以前にインストールしたバージョンで動いているデーモンの残骸を、停止・削除します。

DOCKER_HOST のリセット(unset)

DOCKER_HOST 環境変数の設定は不要です。 bash を使用する場合は、リセットのために unset ${!DOCKER_*} コマンドを使います。他のシェルの場合は、シェルのドキュメントをご確認ください。

ウェブサーバの例で Docker が動作しているのを確認

hello-world-nginx サンプルなどを使い、 Docker Desktop で https://localhost 上にウェブサーバを起動します。メニューバー上に Docker 鯨(のアイコン)があるのを確認し、シェル上の Docker コマンドが Docker Desktop エンジンに接続しているのを確認します(Toolbox のエンジンではありません)。そうしなければ、ウェブサーバ・コンテナは実行できるかもしれませんが、 docker は "web page not available"(ウェブページが表示できません)というエラーを返すでしょう。

'port already allocated' (ポートが既に割り当てられています) エラーを解決するには

Bind for 0.0.0.0:8080 failed: port is already allocatedlisten tcp:0.0.0.0:8080: bind: address is already in use ... のようなエラーが出ることがあるでしょう。

これらのエラーは、Windows 上の他のソフトウェアが各ポートを使っている場合によく発生します。どのソフトウェアが使っているかを見つけるか、 resmon.exe の GUI を使い "Network" と "listening Ports" をクリックするか、 Powershell 上では netstat -aon | find /i "listening " を使って、対象ポートを現在使っているプロセスの PID を見つけます(PID の値は行の右端です)。他のプロセスの停止を決めるか、あるいは、docker アプリで別のポートを使うかを決めます。

アンチウィルス・ソフトウェアをインストールしていると、Docker Desktop の起動に失敗

いくつかのアンチウィルス・ソフトウェアは、Hyper-V と Microsoft Windows 10 ビルドによっては互換性がない場合があります。典型的に発生するのは Windows update 直後で、Docker デーモンからエラーの反応が表示され、Docker Desktop の起動に失敗します。

一時的な回避策としては、アンチウィルス・ソフトウェアをアンインストールするか、Docker Desktop フォーラム上での他の回避策をお探しください。

FAQ(よくある質問と回答)

Stable と Edge リリース

Docker Desktop の Stable か Edge 版を入手するには、どうしたら良いでしょうか?

Docker Desktop の Stable 又は Edge 版は Docker Hub からダウンロードできます。

インストール手順は Windows に Docker Desktop をインストール を御覧ください。

Docker Desktop の Stable 版と Edge 版の違いは何ですか?

Docker Desktop のコミュニティ版では、2つのダウンロード・チャンネルがあります。

Stable チャンネル は、完全に固められ、テスト済みであり、信頼できるアプリケーションとして、一般的に利用可能な準備が調っているリリースのインストーラを提供します。リリース時期は Docker エンジンのリリースとパッチ(修正版)リリースに同期しています。Stable チャンネルでは、利用状況統計や他のデータを送信するかどうか選択できます。

Edge チャンネル は、開発中の新機能を含むインストーラを提供しますが、必要なテストを十分に行っていません。Docker エンジンの実験的なバージョンを含みます。そのため、Edge バージョンの利用時には、バグ、クラッシュなど問題が発生する可能性があります。しかし、新機能のお試しや経験を得られるチャンスとなり、Docker Desktop の進化に対するフィードバックを提供します。一般的に、Edge リリースは Stable に比べ頻繁にリリースがあります。おおよそ、一ヶ月か一ヶ月おきのリリースです。デフォルトで利用統計情報やクラッシュ報告が送信されます。Edge チャンネルでは、これを無効化するオプションはありません。

Docker Desktop の Stable と Edge 版を切り替えできますか?

はい、Stable と Edge 版を切り替え可能です。Edge リリースで何が新しくなったか試してみた後、Stable に戻って他のことができます。しかしながら、 一度に Docker Desktop をインストールできるバージョンは、1つのみ です。詳しい情報は Stable 及び Edge バージョン間の切り替え を御覧ください。

Docker Desktop のシステム動作条件は何ですか?

システム動作条件に関する情報は、 Docker Desktop Windows システム動作条件 を御覧ください。

実験的機能(experimental features)とは何ですか?

実験的機能とは、今後のプロダクト機能を早期に利用できます。各機能のテストやフィードバックのみを目的としており、今後のリリースでは予告のない変更や、将来的なリリースでは機能全体が削除される場合があります。実験的機能はプロダクション環境で利用すべきではありません。実験的機能に対し、Docker はサポートを提供しません。

Docker CLI で実験的機能を有効にするには、config.json ファイルを編集し、 experimental を enabled(有効)にしてください ** 。
Docker Desktop のメニューから実験的機能を有効にするには、 **Settings
(macOS は Preferences )> Command Line をクリックし、それから Enable experimental features トグルを有効に切り替えます。 Apply & Restart (適用と再起動)をクリックします。

どうしたらいいでしょうか?

リモートの Docker Engine API に接続するには?

Docker クライアントと開発ツール用のために、 Engine API の場所を指定する必要があるでしょう。

Docker Desktop では、Docker Engine は、 名前付きパイプ npipe:////./pipe/docker_engineTCP ソケット tcp://localhost:2375 では接続できません。

DOCKER_HOSTDOCKER_CERT_PATH 環境変数のセットを指定します(名前付きパイプ、あるいは TCP ソケットを使ういずれの場合でもです).

Docker Engine API と Docker Desktop for Windows フォーラムのトピック リモート API をどのようにして見つけられますか(英語) も御覧ください。

ホスト上のサービスにコンテナから接続するには?

Windows は変動 IP アドレスを持ちます(あるいは、ネットワーク接続がなければ存在しません)。私たちが推奨するのは host.docker.internal という特別な DNS 名での接続です。これはホストによって使われる内部の IP アドレスを名前解決します。これは開発用途であり、Docker Desktop for Windows 以外のプロダクション環境では動作しません。

また、ゲートウェイには gateway.docker.internal で到達できます。

Docker Desktop for Windows のネットワーク機能についての情報は ネットワーク機能 を御覧ください。

Windows からコンテナに接続するには?

私たちが推奨するのはポートの公開か、他のコンテナからの接続です。コンテナがオーバレイ・ネットワークを使う場合は、Linux と同じような手法が使えますが、ブリッジ・ネットワークの場合は経路付け(ルーティング)されず使えません。

詳細な情報と例は、 ネットワーク機能 の記事にある Windowsからコンテナに接続したい を御覧ください。

ボリューム

コンテナ固有のデプロイに必要となる、共有ボリューム上の権限を変更できますか?

いいえ、現時点では、Docker Desktop はデプロイしたコンテナで 共有ボリューム 上で Unix 風の権限を制御( chmod )できません。それどころか、権限をデフォルトで 0777 の値( usergroup に対する「読み込み」「書き込み」「実行」の権限 )に設定し、変更不可能です。

回避策を学ぶには 共有ボリュームのデータ・ディレクトリ上における権限エラー を御覧ください。

symlink をサポートしますか?

Docker Desktop はコンテナ内で作成したシンボリック・リンク ( symlinks ) をサポートします。 シンボリック・リンクはコンテナ間でも動作します。ただし、Docker の外で作成したシンボリック・リンクは動作しません。

この制限の理由に関する情報を知るには、以下の議論を御覧ください。

証明書

任意の CA 証明書を追加可能ですか?

Docker Desktop は全ての信頼できる(ルート及び中間の)認証局(CA)をサポートしています。Docker は信頼できるルート認証局や中間認証局以下に保管されている証明書を認識します。

サーバとクライアント側証明書の追加に関する情報は、めましょうの記事にある TLS 証明書の追加 を御覧ください。

クライアント証明書の追加はどのように行いますか?

クライアント証明書の追加に関する情報は、始めましょうの記事にある TLS証明書の追加 を御覧ください

コンテナに USB デバイスをパス・スルーできますか?

残念ながら、コンテナに対する USB デバイスのパス・スルーはできません。これは、ハイパーバイザ段階でのサポートが必要だからです。

ネストした仮想化環境で Docker Desktop を実行できますか?

Paralles や VMware Fusion a Mac 上で動く Windows 10 仮想マシン内で、適切に設定を行えば Docker Desktop を実行可能です。しかしながら、ハードウェア仮想化アプリの手法によって、問題や一時的な問題が発生する可能性があります。そのため、 Docker Desktop はネストした仮想化環境での実行をサポートしません 。動く場合もあれば、動かない場合もあります。詳しい情報は ネストした仮想化環境で Docker Desktop を実行 を御覧ください。

VirtualBox と Docker Desktop を併用できますか?

残念ながら、Windows では Hyper-V を有効化しますと、VirtualBox を(及び VMware のような他のハイパーバイザでも)実行できません。

Windows 動作条件

Windows Server 上の Docker Desktop で Windows コンテナを実行できますか?

Windows Server 上で Windows コンテナを実行するためのチュートリアルが、 Windows コンテナを始めましょう にあります。

どうして Windows 10 Home はサポート外なのですか?

Docker Desktop は Hyper-V 機能が必要であり、これは Windows Home ディションでは利用できません。

どうして Windows 10 が必要なのですか?

Docker Desktop は Windows Hyper-V 機能を使います。Windows の古いバージョンでも Hyper-V はありますが、それらの Hyper-V には Docker Desktop を動作するために必要な機能が欠如しています。

アンチウィルス・ソフトウェアをインストールしていると、Docker Desktop の起動に失敗するのはなぜでしょうか?

いくつかのアンチウィルス・ソフトウェアは、Hyper-V と Windows 10 ビルドと互換性がなく、Docker Desktop に影響があります。詳しい情報は トラブルシューティングアンチウィルス・ソフトウェアをインストールしていると,
Docker Desktop の起動に失敗する
を御覧ください。

フィードバック

どのような種類のフィードバックが求められていますか?

全てが対象です。私たちはダウンロード、インストール手順、起動、利用可能な機能、GUI、アプリケーションの使いやすさ、コマンドライン統合、などなど、皆さんの所感を求めています。問題があれば、何をしたいのか、どのような機能が欲しいのかを教えてください。

問題や質問がある場合は、どうしたら良いでしょうか?

診断やトラブルシューティングに関する共通課題の情報は、 ログとトラブルシューティング の記事にあります。

トラブルシューティングで解決策が見つからなければ、 GitHub の Docker Desktop for Windows の issue を見るか、新しい issue を作成してください。また、診断結果に基づいて新しい issue の作成もできます。詳細を学ぶには 問題の診断、フィードバック送信、GitHub issue の作成 を御覧ください。

Docker Desktop for Windows フォーラム には議論のスレッドがあります。そちらでも議論のトピックを作成できますが、私たちが推奨するのはフォーラムではなく GitHub issue を使う方が、追跡可能かつ反応も良いです。

私の利用統計データの送信を停止できますか?

利用統計データの送信を行いたくなければ、 Stable チャンネルを御利用ください。詳しい情報については、 Docker Desktop の Stable と Edge 版の違いは何ですか を御覧ください。

Docker Desktop での個人データの取り扱いはどのようになっていますか?

アップロードされた診断情報は、Docker の問題調査に役立ちますが、ユーザ名や IP アドレスなど個人情報がアップロードされる診断データに含まれる場合があります。診断データにアクセス可能なのは、Docker Desktop の問題を直接解析する Docker, Inc. の従業員のみです。

docker/for-macdocker/for-win の issue トラッカーで、オープンになっていても参照の必要がなければ、Docker, Inc. はアップロードされた診断情報を通常 30 日で削除します。もし issue がクローズされれば、Docker, Inc. は参照された診断情報を 30 日以内に削除します。また、診断 ID かGitHub ID(診断 ID が GitHub issue で使われている場合は)のどちらかで、診断情報の削除要求が可能です。 Docker, Inc. は診断情報のデータを、特定のユーザに対する調査にのみ用いますが、そこから発生する頻度などハイレベル(個人に依存しない)なメトリクスを得る場合もあります。

オープンソース・ライセンス

Docker Desktop エディションはオープンソース・ソフトウェアを用いて構築されています。ライセンスに関する詳細は、 Docker の鯨アイコン → About Docker を選択し、アプリケーション内の Acknowledgements (謝辞)をクリックします。

Docker Desktop エディションは、 GNU General Public License 以下でライセンスされた複数のコンポーネントを配布します。各コンポーネントに関するソースは こちら からダウンロードできます。

qemu-img のソースは こちら から得られます。 qemu-img が必要とする gettextglib ライブラリは Homebrew から得られ、 brew install --build-from-source gettext glib からも得られます。

Stable リリースノート

Edge リリースノート

Docker Desktop WSL 2 バックエンド

新しい Docker Desktop WSL 2 バックエンドは、Docker Desktop WSL 2 Tech Preview の後を継ぐものです。WSL2 バックエンド・アーキテクチャは Kubernetes 向けのサポートを導入し、更新版 Docker デーモンの提供、VPN と親和性のあるネットワーク機能や追加機能を提供します。

WSL 2 は構造上の著しい変更をもたらします。Microsoft によってビルドされた完全な Linux カーネルによって、エミュレーションではなく、ネイティブに Linux コンテナを実行可能になります。WSL 2 上で Docker Desktop を実行しますと、利用者は Linux ワークスペースを活用できるようになり、また、ビルド用スクリプトは Windows 用と Linux 用との両方を準備する必要がなくなります。

また、Docker Desktop は WSL 2 で導入された動的メモリ割り当て機能も活用できるため、リソースの消費を著しく改善します。つまり、Docker Desktop は、コンテナのビルドのような CPU とメモリを大量に必要とするタスクでも、 CPU とメモリを必要量しか使わないため、より速く実行できます。

さらに、WSL 2 はDocker デーモンのコールド・スタート後は、起動に必要な時間が著しく早くなります。Docker デーモンの起動に、現在の Docker Desktop のバージョンでは数十秒かかるのと比べ、2秒以下です。

皆さんのフィードバックは、私たちにとって非常に重要です。どうか皆さんのフィードバックを Docker Desktop for Windows Github リポジトリに WSL 2 ラベルを付けてお寄せください。

動作条件

Docker Desktop WSL 2 バックエンドをインストールする前に、以下の手順を完了している必要があります。

  1. Windows 10 Insider Preview ビルド 19018 以上をインストール。
  2. Windows 上での WSL2 機能の有効化。詳細手順は マイクロソフトのドキュメント を参照ください。

ダウンロード

Docker Desktop Edge 2.1.6.0 以上のリリースをダウンロード。

インストール

Docker Desktop Edge リリースをインストールする 前に 、動作条件のセクションで説明した手順を必ず終えてください。

  1. 通常の Docker Desktop の手順に従って、Docker Desktop をインストールします。
  2. Windows スタート・メニューから Docker Desktop をスタートします。
  3. Docker メニューから、 Settings > General を選択します。 <図>
  4. Enable the experimental WSL 2 based engine (実験的 WSL2 対応エンジンの有効化) のチェックボックスを選択します。
  5. **Apply & Restart* (適用と再起動)をクリックします。
  6. ディストリビューションが WSL2 モードで動作しているかどうかを確認します。WSL はディストリビューションの v1 と v2 モードのどちらでも動作します。

WSL モードの確認は、次のように実行します。

wsl -l -v

v2 にアップグレードするには、次のように実行します。

wsl --set-version <ディストリビューション名> 2

7. Docker Desktop を再起動したら、 Settings > Resources > WSL Integration に移動し、Docker でアクセスしたい WSL 2 ディストリビューションを選択します。
<図>
8. 変更を有効にするには Apply & Restart をクリックします。

原文

Apache License 2.0
https://github.com/docker/docker.github.io/blob/master/LICENSE

Thanks to all Docker developers and contributors and Docker, inc., and you.

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

dockerで自分のnvim環境をどこでも再現する

背景

21卒学生なので、これまで就職活動を兼ねて多くのインターンシップに参加しました。
大抵開発マシンを用意していただいて、初日にこれ使って好きに環境作ってねと言われることが多く、
そのたびに普段の開発環境を再現するのが面倒だった経験があります。

とくに2週間 ~ 1ヶ月くらいの期間のインターンにいくつも参加していると
「これ時間かけて構築してるけど結局使い捨てだししばらくしたらまた違う会社でやり直さないとなんだよな...」と思うことが多くしんどかったです。

自分のマシンを持ち込めればまあ楽なんですが大抵の場合は社内ポリシーによってそうもいかないので、
じゃあもうdockerイメージに固めてpullってくるだけにすれば楽じゃんというのが経緯です。

また普段から複数のマシンやクラウドのインスタンスをいくつも使い分けていて、設定をいじったときに同期するのが面倒というのもあります。

私は基本開発にコマンドラインとnvimしか使わないのでdockerで環境を作るのと相性がよかったという前提があります。

dotfileの共有じゃだめなのか

init.vimやpluginの設定を書いたtomlファイルを管理して、それをcloneしてきて必要なプラグインをインストールするのではだめなのでしょうか。
もともとは私もこの運用をしていましたが、開発環境として考えると次の点が足りず結局追加でセットアップすることになります。

  • python3など動作に必要なランタイム
  • solargraphなど補完に使うLanguage Server
  • prettier, eslintなどのformatterやLinter

これらはvimの外にあるもので、マシンごとにインストールして設定する必要があります。
ただしいつもいつも同じOSを使えるわけではないので共通化しにくく、結局リストアップして手動でインストールする運用をしていました。

これら必要なランタイムやパッケージすらもまとめてしまえば(dockerさえ使えれば)docker registryにあげておいてpullってきて即使えるので非常に楽です。
また環境差もなく完全再現できることも気楽でよいです。

参考

すでに同じようなことをされている方がいたので、こちらを参考にさせていただきました。

個人設定込みNeovimのDokcerイメージを作成した
alpineで設定込みNeovim Dockerイメージのサイズを半減させた

Dockerfile

基本的に参考記事を真似ているので、異なる部分だけ抜粋して解説します。
なお、前提として次のディレクトリ構成になっています。

リポジトリはここ
イメージはここ

.
├── Dockerfile
└── nvim
    ├── dein_lazy.toml
    ├── dein.toml
    └── init.vim
FROM alpine:latest

LABEL maintainer "Akira Shinohara <k017c1067@it-neec.jp>"


# マルチバイト文字をまともに扱うための設定
ENV LANG="en_US.UTF-8" LANGUAGE="en_US:ja" LC_ALL="en_US.UTF-8"

# 最低限必要なパッケージ
RUN apk update && \
    apk upgrade && \
    apk add --no-cache \
    build-base \
    curl \
    gcc \
    git \
    libxml2-dev \
    libxslt-dev \
    linux-headers \
    musl-dev\
    neovim \
    nodejs \
    npm \
    python-dev \
    py-pip \
    python3-dev \
    py3-pip \
    ruby \
    ruby-dev \
    && \
    rm -rf /var/cache/apk/*

RUN pip3 install --upgrade pip pynvim
RUN gem install -N \
    etc \
    json \
    rubocop \
    rubocop-performance \
    rubocop-rails \
    rubocop-rspec \
    solargraph

# install dein.vim
RUN curl -sf https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh \
    | sh -s /root/.cache/dein

COPY nvim /root/.config/nvim

RUN nvim +:UpdateRemotePlugins +qa
RUN chmod -R 777 /root

ENTRYPOINT ["nvim"]

LanguageServerやLinterなど外部ツールもまとめてインストールする

先の通り、dotfileだけでは再現が難しい使っているプラグインが要求するツールやランタイムもこのイメージにまとめてインストールしてしまいます。
そのためにruby-devやnpmなどもインストールしています。

dein.vimを使ってプラグインを管理する

rootユーザの$HOME下にinit.vimやdein.vim本体、プラグイン設定を書いたtomlを展開し、
RUN nvim +:UpdateRemotePlugins +qaでインストールしています。
なにかプラグインを足したりnvimの設定を変えた場合はdockerイメージをbuildすることで反映され、repositoryにpushすることで更新します。

/root以下のパーミッションを777にする

これは正直どうかと思うんですが、一応理由があってのことなので後ほど解説します。

実行

docker run --rm -it -u $(id -u):$(id -g) -e HOME=/root -v $HOME:$HOME --workdir=$(pwd) s10akir/moja-nvim [FILE_NAME]

--rmで一回使い捨てのコンテナを立ち上げ、実行ユーザをホスト側の実行ユーザと合わせた上でゲスト側のhomeディレクトリを/rootに設定し、ホスト側のhomeディレクトリをまるまるマウントして--workdirにホスト側のカレントパスを渡すことで編集するファイルを一致させています。
これによってホスト側のファイルをdockerの存在を意識せずに編集できるようになりました。

長いのでvimにaliasを貼っています。

homeディレクトリごとマウントすることでディレクトリ構造とパスを完全一致させた

参考記事だとカレント以下をマウントしていますが、例えば.prettierrcなどがプロジェクトルートにある場合、常にプロジェクトルートから実行しなければ設定が読み込まれずとんでもないことになります。
私は普段コマンドラインで頻繁にディレクトリを移動しながらファイルを開いたり閉じたりするので結構深刻です。
また、nvim内から親ディレクトリを参照できなくなるのも不便です。

いっそのことhomeディレクトリごとマウントしてしまうことで、難しいことを考えずに必要な親ディレクトリを辿れるようにしました。
$HOMEより上はさわれませんがまあそもそもそれらのファイルって大体rootユーザでいじるようなものなので、触れなくて困らないかなと思っています。

実行ユーザがrootのせいでファイルパーミッションがroot:rootになってしまう問題を解決した

一番苦労した点です。

特に何も考えずにそのままdockerで走らせてしまうとdocker側の実行ユーザがrootになるため、編集したファイルはホスト側からはroot:rootになってしまいます。
既存ファイルを編集した場合には問題ありませんが、これはものすごく不便なのでなんとかして解決したく非常に苦労しました。

というのも、dockerイメージのビルド時点ではホスト側のユーザidがいくつなのか関与することができず事前にユーザを用意できません。
これによりdocker run時に実行ユーザを変えてしまうと今度homeディレクトリが存在しないので、事前に構築したnvimの設定が使えません...

dockerイメージ内に確実に存在しているのはrootユーザであり、nvimの設定が記述されているのもrootユーザです。
当初docker内でシステムグローバルにこれらを管理できないか試していましたが、init.vimはともかくプラグイン管理は難しく諦めました。

結果として、nvimの設定構築後に/rootのパーミッションをゆるくしてしまい、dockerコンテナ実行時に実行ユーザを変えた上でhomeディレクトリを/rootに設定してnvimの設定群を自由に触れるようにしてやればよいのではという形で解決しました。
これが先のRUN chmod -R 777 /rootの理由です。

気持ち悪さの残る解決法ですが、まあ運用上は一回ごとにコンテナを捨てるし、ファイルの編集以外に使わないしまあいいか...という妥協をしています。

ちなみにmacの場合はなんか知らんけどゲスト側で作成したファイルのパーミッションがホスト側の実行ユーザに合わせられるのであんま気にする必要がありません。

オーバーヘッド

ほぼ感じません。というか気になってません。
ホストがLinuxなのもあってか、普通にnvimを立ち上げるのとあんま変わらないくらいの速度で起動してくれます。

Peek 2020-02-27 23-55.gif

終わりに

それなりの期間この環境でのnvimを常用していますが、特別ストレスは感じていません。dockerで動かしてることを忘れるくらいです。
インターンなりバイトなりで初めてのマシンを使うときの環境構築も数分で終わるようになりましたし、気分転換に環境をクリーンにすることも気楽にできるようになりました。

気になっている点としては、

  • クリップボードが共有されない
  • rootユーザより実行専用の別ユーザを作ったほうがいいんじゃないか

くらいです。
クリップボードに関してはXのソケットを共有すれば解決できそうな予感がするのでそのうちやろうかと思ってます。
ユーザに関してはまあ...いいかな別に...パーミッション問題は解決したし......

ただいい感じに落ち着いてきた頃に就活が終わってもういろんな会社に行かなくなったのでもうちょっと早く挑戦しときゃよかったなとなりました。

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