20200126のdockerに関する記事は12件です。

DockerでCMakeビルド環境を作る

はじめに

  • WindowsPC上で、Linuxに対応したCppプロジェクトを作成したい
  • CMakeのDockerコンテナを探しても見つからなかったので今回作成した

良い点

  • ローカルフォルダをマウントするよう設定
    • ローカルフォルダ上でコードを編集すると、すぐにコンテナへ変更が反映される
    • コンテナにログインせずとも、VS code などのエディタで編集できる
    • ビルド後のファイルもdocker cp コマンドを使わずに取り出せる

ダウンロード

  • この記事で紹介したDocker imageは、DockerHub からダウンロードすることができます。

フォルダ構成

  • 下図のようにDockerfile, docker-compose.ymlを配置する
    • ソースコードは記事の下部に記載
  • cppフォルダは、docker-compose up によって自動生成される
    • このフォルダ内に ソースコードを置く
tree
フォルダ構成
├── Dockerfile
├── docker-compose.yml
└── cpp  ← 自動生成される

Dockerfile

Dockerfile
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y sudo && \
    apt-get install -y vim && \
    apt-get install -y wget

# Install compilers.
RUN apt-get install -y gcc && \
    apt-get install -y g++

RUN apt-get install -y cmake 3.10.2

# SET path to compilers.
# https://stackoverflow.com/questions/17275348/how-to-specify-new-gcc-path-for-cmake
ENV CC=/usr/bin/gcc \
    CXX=/usr/bin/g++

# OpenBlas, Lapack
RUN apt-get install -y libopenblas-dev  && \
    apt-get install -y liblapack-dev

# Please use below directory to install cpp libraries.
WORKDIR $HOME/usr/
RUN mkdir /library

CMD ["bash"]

docker-compose.yml

docker-compose.yml
version: '3'

services:
  cmake:
    container_name: cmake_container
    build:
      context: .
      dockerfile: Dockerfile

    tty: true
    command: /bin/bash

    volumes:
      - ./cpp:/usr/cpp

使い方

コンテナの起動

ローカル環境
# コンテナの初回起動
docker-compose up -d

# 起動中のコンテナに入る
docker-compose run cmake

ソースコードのコンパイル

@make_container
# コンテナ内のcppフォルダに入る
cd cpp

# build フォルダを作成し入る
mkdir build
cd build

# cmakeの実行
cmake ../

# makeの実行
make

活用例

  • ①cppフォルダ内に、.cppファイルやCMakeLists.txtを置く
    • VSCodeなど、自分の使い慣れたエディタで編集する
  • ②コンテナ内に入り、ビルド実行
  • ③ビルド後のファイルは、ローカル環境のcppフォルダから取り出すことができる image.png

注意点

  • OS依存のライブラリは、cppフォルダ内で展開・インストールしないでください
    • 筆者は以下のエラーメッセージが表示され、コンテナのマウントが解除されてしまいました。
    • docker compose error while creating mount source path...
    • 依存ライブラリはコンテナ内で別フォルダを作り、そこにインストールしてください
      • 例) OpenCV

チュートリアル

  • 以下では、Hello CMake!と書かれたソースコードをビルドするまでをご紹介します。
  • cppフォルダ内に以下の2つのファイルを作成してください。
cppフォルダ内の構成
cpp
├── main.cpp
└── CMakeLists.txt
  • 各ファイルに以下の内容をコピーしてください。
main.cpp
#include <iostream>
#include <string>

int main(void){
    std::cout << "Hello CMake!" << std::endl;
    return 0;
}
CMakeLists.txt
# プロジェクト名
project("testCMake")

# CMakeのバージョンを設定
cmake_minimum_required(VERSION 2.8)

# testCMake.outという実行ファイルをmain.cppから作成
add_executable(testCMake main.cpp)
  • 次に、コンテナでのビルド作業に入ります。
  • 以下のコマンドを順に入力してビルドします。
@cmake_container
# コンテナ内のcppフォルダに入る
cd cpp

# ビルドフォルダを作る
mkdir build
cd build

# ビルド実行
cmake ../
make
  • 最後にビルドしたプログラムを走らせてみましょう!
    • ./testCMakeと入力し、Hello CMake!と出力されれば成功です。
@cmake_container
./testCMake 
Hello CMake!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CMake on DockerでC++コードを簡単ビルド

はじめに

  • WindowsPC上で、Linuxに対応したCppプロジェクトを作成したい
  • CMakeのDockerコンテナを探しても見つからなかったので今回作成した

良い点

  • ローカルフォルダをマウントするよう設定
    • ローカルフォルダ上でコードを編集すると、すぐにコンテナへ変更が反映される
    • コンテナにログインせずとも、VS code などのエディタで編集できる
    • ビルド後のファイルもdocker cp コマンドを使わずに取り出せる

ダウンロード

  • この記事で紹介したDocker imageは、DockerHub からダウンロードすることができます。

フォルダ構成

  • 下図のようにDockerfile, docker-compose.ymlを配置する
    • ソースコードは記事の下部に記載
  • cppフォルダは、docker-compose up によって自動生成される
    • このフォルダ内に ソースコードを置く
tree
フォルダ構成
├── Dockerfile
├── docker-compose.yml
└── cpp  ← 自動生成される

Dockerfile

Dockerfile
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y sudo && \
    apt-get install -y vim && \
    apt-get install -y wget

# Install compilers.
RUN apt-get install -y gcc && \
    apt-get install -y g++

RUN apt-get install -y cmake 3.10.2

# SET path to compilers.
# https://stackoverflow.com/questions/17275348/how-to-specify-new-gcc-path-for-cmake
ENV CC=/usr/bin/gcc \
    CXX=/usr/bin/g++

# OpenBlas, Lapack
RUN apt-get install -y libopenblas-dev  && \
    apt-get install -y liblapack-dev

# Please use below directory to install cpp libraries.
WORKDIR $HOME/usr/
RUN mkdir /library

CMD ["bash"]

docker-compose.yml

docker-compose.yml
version: '3'

services:
  cmake:
    container_name: cmake_container
    build:
      context: .
      dockerfile: Dockerfile

    tty: true
    command: /bin/bash

    volumes:
      - ./cpp:/usr/cpp

使い方

コンテナの起動

ローカル環境
# コンテナの初回起動
docker-compose up -d

# 起動中のコンテナに入る
docker-compose run cmake

ソースコードのコンパイル

@make_container
# コンテナ内のcppフォルダに入る
cd cpp

# build フォルダを作成し入る
mkdir build
cd build

# cmakeの実行
cmake ../

# makeの実行
make

活用例

  • ①cppフォルダ内に、.cppファイルやCMakeLists.txtを置く
    • VSCodeなど、自分の使い慣れたエディタで編集する
  • ②コンテナ内に入り、ビルド実行
  • ③ビルド後のファイルは、ローカル環境のcppフォルダから取り出すことができる image.png

注意点

  • OS依存のライブラリは、cppフォルダ内で展開・インストールしないでください
    • 筆者は以下のエラーメッセージが表示され、コンテナのマウントが解除されてしまいました。
    • docker compose error while creating mount source path...
    • 依存ライブラリはコンテナ内で別フォルダを作り、そこにインストールしてください
      • 例) OpenCV

チュートリアル

  • 以下では、Hello CMake!と書かれたソースコードをビルドするまでをご紹介します。
  • cppフォルダ内に以下の2つのファイルを作成してください。
cppフォルダ内の構成
cpp
├── main.cpp
└── CMakeLists.txt
  • 各ファイルに以下の内容をコピーしてください。
main.cpp
#include <iostream>
#include <string>

int main(void){
    std::cout << "Hello CMake!" << std::endl;
    return 0;
}
CMakeLists.txt
# プロジェクト名
project("testCMake")

# CMakeのバージョンを設定
cmake_minimum_required(VERSION 2.8)

# testCMake.outという実行ファイルをmain.cppから作成
add_executable(testCMake main.cpp)
  • 次に、コンテナでのビルド作業に入ります。
  • 以下のコマンドを順に入力してビルドします。
@cmake_container
# コンテナ内のcppフォルダに入る
cd cpp

# ビルドフォルダを作る
mkdir build
cd build

# ビルド実行
cmake ../
make
  • 最後にビルドしたプログラムを走らせてみましょう!
    • ./testCMakeと入力し、Hello CMake!と出力されれば成功です。
@cmake_container
./testCMake 
Hello CMake!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでMysqlコンテナを作る

この記事について

dockerコマンドをよく忘れるのでメモしておきます
mysqlを例にしています。
ただの備忘録です

docker pull Dockerイメージの取得

docker pull mysql

docker images -a Docker イメージの一覧を表示

docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               latest              3a5e53f63281        11 days ago         465MB
mysql               <none>              d5127813070b        2 years ago         407MB

docker run コンテナの作成

docker run --name mysql-for-test -e MYSQL_ROOT_PASSWORD=password -d -p 13307:3306 mysql:latest

-dはコンテナをバックグラウンド実行するオプション
docker run

docker start [name] コンテナの起動

docker start mysql-for-test
mysql-for-test

docker ps -a 現在実行中のコンテナの確認

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
a0371102cea6        mysql:latest        "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        33060/tcp, 0.0.0.0:13307->3306/tcp   mysql-for-test

docker stop [name] コンテナの停止

docker stop mysql-for-test
mysql-for-test

docker rmi イメージ削除

docker rmi mysql:latest
Untagged: mysql:latest
Untagged: mysql@sha256:f1df505c4c6e8eae599a0482e3bde3e761cd700c00cbc371a8161648a26817c0
Deleted: sha256:3a5e53f6328162f8d8bc70131658a721e8e7dcf7495f2fae7cfe4febdbcfefbb
Deleted: sha256:f2533710d884b7eb9329d63844e1504c2d166cdb9139be622f9a5ed5dbd8044c
Deleted: sha256:573b1ee1cfefd4e3c18ade60576f03e275e28b73d985ce551ae78b1a93a81ace
Deleted: sha256:a7de8634d9c2f1188b74aceb18c048e37ea86eace1c4614996e76abc065e71fb
Deleted: sha256:96b788fd084094ed5b2b00b29865ec25bdba4aba633b8a86bb7e485df21e9dfb
Deleted: sha256:c1f124fbef5b35b53dadbd9caa1a272bde42490963ec68daa0a0e52a516cf5f9
Deleted: sha256:5f7c68324b959d2c806db18d02f153bc810f9842722415e077351bc834cc8578
Deleted: sha256:338fc0cd3fb4b87a2b83d274e8fbf475fbde19947c4ac5c5eb6e981a6fb0e8f0
Deleted: sha256:f7a4ccab931f1d1e861961eb951a7806d91ccb375e737fe1f84282f6bbafd2be
Deleted: sha256:f388e1092f8fb931a3cd07a7381bd9707d19526ff81f8b624e932f4919c27a3e
Deleted: sha256:e209b7a884b4d2e9d56bbac40ced48f2caa6a19e7ad6eb6dd20ff754f3af2c5d
Deleted: sha256:2401cf11c5455d505ef49657afcc709197ffcdfc9bd732508e9b62578a30b3a5
Deleted: sha256:814c70fdae62bc26c603bfae861f00fb1c77fc0b1ee8d565717846f4df24ae5d

コンテナ起動時はコンテナに使用しているイメージは削除できない

MySQL Workbenchで接続する設定

上記の例だと
IP 127.0.0.1
Port 13307
username root
Password password
で繋がるはず

docker volume ls Dockerボリュームを表示する

docker volume ls
DRIVER              VOLUME NAME
local               4af0b51aff028e66d409e273378cbae94384a5a19ad4d2b2e22020a050c2f1ab

docker volumeとはデータを永続化する場所とのこと
Mysqlのコンテナを作成するとVolumeも作成されています。
イメージやコンテナを削除してもVolumeは削除されない
Docker、ボリューム(Volume)について真面目に調べた

docker inspect [ボリューム名] Dockerボリュームの詳細を表示する

docker inspect 4af0b51aff028e66d409e273378cbae94384a5a19ad4d2b2e22020a050c2f1ab
[
    {
        "CreatedAt": "2020-01-26T11:30:51Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/4af0b51aff028e66d409e273378cbae94384a5a19ad4d2b2e22020a050c2f1ab/_data",
        "Name": "4af0b51aff028e66d409e273378cbae94384a5a19ad4d2b2e22020a050c2f1ab",
        "Options": null,
        "Scope": "local"
    }
]

docker volume rm [ボリューム名] Dockerボリュームを削除する

docker volume rm e50120cd5bd6f95e469e056390285e62d4607cb171578ab965c404bd9cc6ac35
e50120cd5bd6f95e469e056390285e62d4607cb171578ab965c404bd9cc6ac35

使用中のボリュームを削除しようとした場合は以下のようにエラーが出て削除できません

docker volume rm e78cc14f113a5604b8ce19be097b9a293bf10e35ea17d0643ebfe8f1b875e416
Error response from daemon: remove e78cc14f113a5604b8ce19be097b9a293bf10e35ea17d0643ebfe8f1b875e416: volume is in use - [d78ae59aa2db6328999a0a02b552a72f5f8bf7ef047673778323fe1b4d276c7a]

docker volume prune 停止しているコンテナのDockerボリュームを一括削除する

docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
9f2e7aece432721df0c486f424deaac4fd2ec599164f5dc942c68cb81cbed8b1
4af0b51aff028e66d409e273378cbae94384a5a19ad4d2b2e22020a050c2f1ab
d8158a2830563c99eb8907feacbe85da49f7186e9d4464d6e4ccc0666cd66b44
44e1f3a93792855219d361a11381fc5ce21eb7bac7f6940ef2617ebcb916c74e
d296e6bf49ecb4da2a84589ce1d7439621eedd1242fc979cfcff6636e175f568
e4a3ffc963c51b5d86e787344ee483215c354a8f72bbe6640a51d9c9760b8e5c

Total reclaimed space: 891.7MB

docker volume create [ボリューム名] Dockerボリュームを新規作成する

docker volume create mysql-test-volume
mysql-test-volume

Dockerボリュームを指定してコンテナを作成する

docker run --name mysql-for-test -v mysql-test-volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d -p 13307:3306 mysql:latest
eb61f634a9b04e86e81470096489938cac77682e20be551c961f7395d18fc836

これでデータが永続化される・・・はず。

今度書く

docker-compose使う方法

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

簡単なForm作成から学ぶVue(TypeScript)の書き方 その0 環境構築編

Dockerを用いてVue環境を作り、いい感じのフォームを作成しながらVueを学習していく。

Dockerざっくりした理解

Dockerコンテナ

→ アプリケーションの実行環境
ホストOS上に論理的な区画を作ったもの。OSやIPアドレスなどのシステムリソースをコンテナが見かけ上占有できる。
コンテナに必要なモジュールのみを詰めてアプリケーションを実行できる。

Dockerイメージ

→ コンテナを構成するための設計図。
DockerHubを介して種々のイメージを共有できる。

Dockerコマンドの利用

よくあるDockerの練習としてnginxを用いたサーバー構築がある。

nginxでサーバー構築
$ docker pull nginx                  //DockerHubからイメージ取得
$ docker run --name webserver -d -p 80:80 nginx //起動。デーモン化。ブラウザからアクセスできるようになる。
$ docker ps                       //プロセス確認
$ docker stop webserver                //停止
$ docker rm webserver                  //削除

Dockerfile

→ DockerfileはDockerイメージを構成するための構成情報ファイル。
上の練習ではDockerHub上のイメージを取得し、そのまま起動させるものだが、実際の開発では、内部の構成に手を加え、独自のイメージを創り、コンテナを生成することとなる。
コマンドで環境を構築してもよいが、本格的な開発となった場合に以下のような構成情報を別途ドキュメントとして残す必要が出てしまう。

  • 元となるDockerイメージ
  • コンテナ内で実行するコマンド
  • 環境変数などの設定値

こうした構成情報を記述しておくファイルがDockerファイルであり、docker buildコマンドを用いると、このDockerfileを元にしてDockerイメージを作成できるため無駄やミスがない。

Docker Compose

これまでのDockerは1つのコンテナを用いる話だった。先述の通りコンテナは論理的に1区画を創るものであり、複数のコンテナを生成することもできる。複数のコンテナを生成し、それらをコンテナ内部のネットワークで繋ぐこともできる。

これらを束ねるのがdocker-composeであり、その設定ファイルがdocker-compose.ymlである。

vue環境の構築

参考→https://cloudpack.media/43078

正直この通りやっていけばできる。複数選択のものはスペースで選択できる。
設定は少し変更あり。

Dockerfile
FROM node:10.8.0-stretch

RUN npm install --global @vue/cli

WORKDIR /projects
docker-compose.yml
version: '3'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ".:/projects"
    tty: true
$ docker-compose up -d
$ docker-compose exec app bash
設定部分
# vue create app

Vue CLI v4.0.5
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Basic(一番目を選択)
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: Mocha
? Pick a E2E testing solution: Cypress
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: NPM

構築が終わったらappディレクトリに移行して下のコマンドを実行。ブラウザからlocalhost:8080にアクセスして確認。

 # cd app
 # npm run serve

ctrl+Cで終了し、exitでDockerから抜けた後$ docker-compose downでコンテナごと終了。

お世話になった参考サイト

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

コード内で環境名 (dev,stg,prod) を使用しないことのすすめ

サービスを運用する場合、開発、運用で複数の環境でサーバーを動かしている場合がよくあると思います。このとき、パラメータ設定の口が柔軟でないと設定値の変更がしにくかったり、サーバーのビルドを環境毎にしなければならなず(特に docker 使っている場合)、デプロイに時間がかかったりします。
そうならないために環境名 (dev,stg,prod) を使用して動作変更するのをやめることをおすすめします。記事内では以下のような環境があると想定し、Javascript (Node.js) でいくつかの例を示します。

  • 開発時ローカル PC
  • ステージングサーバー環境
  • 本番サーバー環境

変数を環境名に依存させるのをやめよう

サーバーでエラーが起きたときに管理者にメールを送るというケースで送り先を分ける場合で説明します。

悪い例(コード内で環境ごとのメールアドレスを決めている)

コード内で設定されているアドレスにしか送ることができません、送信するメールアドレスが変更になったときはコードの変更が必要。

// process.env.NODE_ENV に環境名が指定されている
function sendErrorMail() {
  let email = 'default@example.com';
  switch(process.env.NODE_ENV) {
  case 'development':
    email = 'dev@admin.com';
    break;
  case 'staging':
    email = 'stg@admin.com';
    break;
  case 'production':
    email = 'prod@admin.com';
    break;
  default:
    break;
  }
  // sendMail は email アドレスとメール本文を指定してメールを送る関数
  sendMail(email, 'Server Error Occurred');
} 

良い例(環境変数としてメールアドレス自体を指定している)

メールアドレスが変更になったときでも環境変数の指定を変更するだけで送信先が変更できる

// process.env.ADMIN_EMAIL_ON_ERROR にエラー時のメール送り先が指定されている
function sendErrorMail() {
  // sendMail は email アドレスとメール本文を指定してメールを送る関数
  sendMail(process.env.ADMIN_EMAIL_ON_ERROR, 'Server Error Occurred');
} 

動作を環境名に依存させるのをやめよう

次も似た例ですが、ログのレベル設定を例に説明します。 logWarn という警告ログを出力する関数があるとします。開発環境だったら debug ログを出す、というパターンはよくあると思いますが、一つの環境変数としてログレベルを設定すると柔軟です。

悪い例(コード内で環境名でレベルを決めている)

// process.env.NODE_ENV に環境名が指定されている
function logWarn(message) {
  if (process.env.NODE_ENV == 'development') {
    console.warn(message);
  }
}

良い例(ログレベルを環境変数として設定する)

const LogLevel = {
  DEBUG: 0,
  INFO: 1,
  WARN: 2,
  ERROR: 3,
  TRACE: 4,
};

// process.env.LOG_LEVEL にログレベルが設定されている
function logWarn(message) {
  if (process.env.LOG_LEVEL <= LogLevel.WARN) {
    console.warn(message);
  }
}

最後に

この話は主流にありつつある(すでに主流?) Docker でのサーバーデプロイの背景が大きいです。Docker image を build して デプロイしてという流れで運用している場合、ちょっとした動作の変更によって Docker image の build し直ししなければならないとか、環境毎に image を build し直さなければけ無いとなると、build 時間はわりとかかるケース(色々なケースがありますが、数分から10分は最低でもかかると思います)が多いので、build し直ししなくてもいいように(実行時に環境変数として設定すればいいだけにするために)設定類は個別の設定毎に外出ししていくと便利だと考えています。

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

GoとRedisでAPIを実装する (Part.1)

はじめに

本記事では、Go 言語と Redis を使用し簡単なAPIの作成手順について説明する。docker-compose を使って実装していく為、環境に依存しない開発環境で実装する。効率的に開発が行える様、開発の中でいくつかの工夫を施しているので参考になれば幸いである。

また、今回は記述量が多くなるので以下の2部構成にした。

  • Part.1 : 環境構築 ~ 動作確認
  • Part.2 : API実装 ~ 実装検証

本記事では環境構築から動作確認までを説明する。

初めて実装していく方の為に、実行環境と予備知識としていくつか説明する。

1. 実行環境

  • macOS Catalina Ver.10.15.2
  • Docker version 19.03.5, build 633a0ea
  • docker-compose version 1.24.1, build 4667896b
  • golang 1.13.6
  • Redis 5.0.7

【補足①】

  • Go言語
    • 2009年、Googleによって開発されたオープンソース(OSS)のプログラミング言語。
    • 特徴として、「高速コンパイル」、「シンプルな記述」が挙げられる。

【補足②】

  • Redis
    • キーバリュー型(KVS)の NoSQL の一種。
    • キーと5種類の値型の対応関係を格納ができる。
    • インメモリデータベースであるため、高速なデータへのアクセスが可能である。

【補足③】

  • Docker
    • コンテナ型の仮想化ツール。
    • 従来のハイパーバイザ型(Hyper-V)、ホスト型(VMWareやVirtualBoxなど)に比べ軽量で、且つ利便性が高い。
    • docker-compose を使用する事で、複数のコンテナを組み合わせて1つのアプリケーションを構成できる。

2. 前提条件

今回、実装するに至って用意するべき事項は以下の2点である。

  • PC内に docker、docker-composeがインストールされている
  • Goの開発環境が整備されている

docker、docker-compose が動作する環境があれば、特必要となるものは無い。コードを書く際は、好みのエディター (Atom、VSCodeなど)を使用すると良い。Goの開発環境に関しては、開発を進める上でgo.modgo.sumを事前に作成しておく必要がある為、インストールしている。

Goの開発環境に関しては、Homebrewを使用した環境構築がオススメである。以下にインストール手順を示しておく。

$ brew install go

尚、今回使用するものが正常にインストールされているかどうかを確認したい場合は、以下のコマンドで確認が可能である。

# Goの確認
$ go version
go version go1.13.6 darwin/amd64

# dockerの確認
$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
...

# docker-composeの確認
$ docker-compose version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
...

3. 環境構築

3.1. ファイル構成

今回のファイル構成は以下の通りである。

sample_project
├── docker
│   ├── api
│   │   └── Dockerfile-api //API用
│   └── database
│       └── Dockerfile-redis //DB用
├── docker-compose.yml
└── src
    └── app
        ├── controller
        │   ├── sender.go
        │   └── receiver.go
        ├── infrastructure
        │   └── database.go
        ├── interface
        │   └── user.go
        └── main.go

今回は個々の処理を各ディレクトリに分けた。構成に関しては様々な設計思想があると思うので、それに基づいて開発を行う場合は、はじめにファイル構成などを考えてから構築して行くと良い。

3.2. Go Modulesの作成

GoではGo Modulesと呼ばれる外部パッケージの管理システムがある。今回はそれを使用する為、事前にmain.goが配置されているディレクトリで以下のコマンドを実行し、go.modgo.sumを作成しておく。

# appディレクトリまで移動
~/sample_project $ cd src/app
# go.modファイルを作成する
~/sample_project/src/app $ go mod init main.go

# go build コマンド、または go mod download コマンドのどちらかを実行する
~/sample_project/src/app # go build
~/sample_project/src/app # go mod download

次に、Dockerfileの作成する。

3.3. Dockerfileの作成

3.3.1. Dockerfile (API)

まず、API用のDockerfileを作成していく。API側のDockerfileではGoの環境を構築していく。開発環境ではソースコードが随時更新される事を考慮し、ホットリロード環境を導入するためにfreshと呼ばれるライブラリを使用した。

Dockerfile-api
###############################
# Builder Container
###############################
FROM golang:1.13.6 AS builder

# Go Moduleが使えるようにする
ENV GO111MODULE=on

WORKDIR /go/src/app/

# GOROOTが/goになるため
COPY src/app /go/src/app

# gormとginのドライバをインストールする
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git && \
    go mod download && \
    go get github.com/pilu/fresh && \

# ホットリロードを実行する
CMD ["fresh"]

###############################
# Production Container
###############################
FROM golang:1.13.6-alpine AS production
COPY --from=builder /go/src/app/ /app

上記の様に、開発環境と本番環境とで環境を分ける為、マルチステージビルドしても良い。マルチステージビルドを使用する事で、可読性、保守性を保つ事ができる。また、逐一Dockerfileを最適化するために書き直す面倒くささも解消できる。

尚、環境を分割する必要のない場合、以下の記述例でも良い。

Dockerfile-api-slim
FROM golang:1.13.6-alpine

ENV GO111MODULE=on

WORKDIR /go/src/app/

COPY src/app /go/src/app

RUN apk add --no-cache --virtual alpine-sdk git && \
    go mod download && \
    go get github.com/pilu/fresh

CMD ["fresh"]

alpineを使用する事で、イメージが軽量化されるので、ビルド時間の短縮にもなる。しかし、RUNコマンドの記述が上記とは異なる為、注意してほしい。

alpine : Alpine Linuxと呼ばれる、BusyBoxとmuslをベースにしたLinuxディストリビューションを指す

今回は、簡単なAPIの実装なのでDockerfile-api-slim(alpineの方)を使用して開発を行う。

3.3.2. Dockerfile (Database)

DB用のDockerfileを作成していく。DB側のDockerfileではRedisの環境を構築していく。
こちら側では今回、特に設定をする事はないので下記のような記述で良い。

Dockerfile-database
FROM redis:5.0.7-alpine

Dockerfileの作成は以上である。

3.4. docker-compose.yml

次に、docker-compose.ymlの作成を行う。

docker-compose.yml
version: '3.7'
services:
  api:
    build:
      context: .
      # マルチステージビルドを使用しない場合、targetは不要
      target: builder
      dockerfile: ./docker/api/Dockerfile-api
    container_name: sample_project-api
    image: sample_project/api:0.1.0
    ports:
      - "8080:8080"
    # ホストOSとコンテナ内でソースコードを共有
    volumes:
      - ./src/app:/go/src/app
    depends_on:
      - redis
    tty: true

  redis:
    build: 
      context: .
      dockerfile: ./docker/database/Dockerfile-database
    container_name: sample_project-redis
    image: sample_project/redis:0.1.0
    ports:
      - "6379:6379"
    restart: always
    volumes:
      - ./docker/database:/data

今回の実装の場合、DB側のコンテナの起動が完了してからAPIのコンテナを起動させたいので、
depends_onでコンテナの作成順序を依存関係を決めている。

また、tty:trueを追記する事でコンテナを常時起動させる。ポート番号に関しては、デフォルトの80806379をそれぞれ設定している。

マルチステージビルドを採用している場合は、targetの箇所で、自分がビルドしたいステージを指定すると良い。

3.5. main.go

コンテナのイメージを作成後に正しく環境構築されているかどうかを確認するために、main.goの作成をしておく。ここでは、簡単に作成し、後ほどAPIの開発のために改修していく。

以下に作成したソースコードを示す。

main.go
package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()
    router.GET("/", func(context *gin.Context) {
        context.JSON(200, gin.H{
            "message": "Hello, World!!",
        })
    })
    router.Run(":8080")
}

今回は、GoのWebフレームワークの1種である、Gin を使用した。処理の内容としては、http://localhost:8080/へアクセスすることでHello, World!!とメッセージが返ってくるだけの簡単なものである。

3.6. dockerイメージの作成

Dockerfile, docker-compose.ymlを作成後、以下のコマンドを実行し dockerイメージを作成する。

~/sample_project $ docker-compose up -d

実行後、イメージができているかどうかを以下のコマンドを実行し、確認する。

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
sample_project/redis   0.1.0               b68707e68547        9 days ago          29.8MB
redis                  5.0.7-alpine        b68707e68547        9 days ago          29.8MB
sample_project/api     0.1.0               f8d6549bee6c        24 minutes ago      449MB
golang                 1.13.6-alpine       9954d1348cd8        10 days ago         359MB

3.7. コンテナの起動 / 動作確認

イメージの作成後、以下のコマンドを実行しコンテナを起動させる。

$ docker-compose up

# docker-composeコンテナ一覧の確認
$ dokcer-compose ps
       Name                      Command               State           Ports         
--------------------------------------------------------------------------------------
sample_project-api     fresh                            Up      0.0.0.0:8080->8080/tcp
sample_project-redis   docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp

コンテナを起動後、http://localhost:8080/ へアクセスするか、またはcurlコマンドを実行する事で確認できる。

$ curl localhost:8080
{"message":"Hello, World!!"}

また、redisの接続確認は以下のコマンドの通りである。

# コンテナ内部に入る
$ docker exec -it [CONTAINER ID] sh
# redis-cliの起動
/data # redis-cli
# 以下のIPアドレスに入れればOK
127.0.0.1:6379>

以上まで確認できれば、一通りの環境構築、動作検証は終了である。

4. まとめ

今回は環境構築から動作確認までを行った。今回の構成を真似しなくとも、ホットリロード環境は便利なので今後参考にして頂ければと思う。

次回は、この続きでAPIの実装を行っていく。

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

Docker+ROSの環境をWindows10PROで整える

書いた理由

Docker+ROSで開発する人は多くいて、懇切丁寧なチュートリアルがDockerHubのROSのリポジトリにも書いてありますが、私のようにまったくDocker使ったことない人には、Dockerの使い方やコマンドからメモっておかないと使えません(泣)
3日経ったらやり方を忘れてしまうと思って備忘録代わりに書いておきます。

環境

Windows10Pro
HomeエディションではHyperVを使用できなかったため、アップグレードして使用しました。

想定する使い方

WindowsのDockerコンテナにハードウェアをマウントすることは2020/01/26現在は無理のようです。
WindowsPCとJetson-nanoを無線LANでつなぎ、ハードウェアの集まるJetson-nanoとROSでデータを交換しながら開発する。
最終的にはJetson-nano単独で動かしますが、開発だけでも大きなPCでできれば楽ができます。

Docker+ROSの環境で開発したい

Jetson-nanoにつないだ小さなディスプレイで開発するのが大変になってきたので、Windows10をProにアップグレードしてDocker DeskTopを使うことにしました。
DonkeyCar用にAnacondaの環境が入っているので、競合を回避するのが目的です。
また、DockerHubのリポジトリを持ってくることで環境構築の負担を減らすのが目的です。
もともと仮想マシンでUbuntuを入れてみましたが、うまく動かないのでDockerに宗旨替えしました。

Docker Desktopのインストール

https://www.docker.com/products/docker-desktop
公式のマニュアルに沿ってインストールします。
Windows10Proじゃないと、HyperVが動かないので使えません。
HyperVを有効にして再起動したらあっさり動きました。
GUIでDockerHubのユーザーIDとかを設定しておきます。

ROSのイメージをPULLしてみる

適当なディレクトリを作って、コマンドを開いて、
docker pull ros
これでDockerHubからROSのリポジトリを引っ張れました。
バージョンを指定するときは、
docker pull ros:melodic
とかするとOK。

ROSのイメージの中で作業する

docker run -it --name test ros
pullしたコンテナイメージを動かし、コンテナの中で作業できます。

-it コンテナのSTDINにアタッチし疑似ターミナルを割り当て
-name ホスト名を決めてコンテナ起動

ROSコンテナにtoolをインストール

catkin buildが動かないので、ツールは公式イメージに入っていないらしいです。
コンテナの中でツールをインストールします。
sudo apt install python-catkin-tools
では何故かインストールできなかったので、apt-getを使いました。

ROS
sudo apt-get update
sudo apt-get install python-catkin-tools

で、セットアップ完了。

ROS
mkdir -p catkin_ws/src/
cd ..
catkin build

これでパッケージのビルドができるようになりました。

exit で抜けることができます。抜けてもコンテナは動作している状態です。
再度、開始とアタッチをするなら

command
docker start test
docker attach test

コンテナイメージのバックアップ

exitした後、タグをつけてイメージを保存します。

command
docker commit test ros:ros-test

このタグを使って新しいイメージを起動します。名前は先ほど使ったtestを使うとコンテナ名が重複するのでNG。

command
docker run -it --name build ros:ros-test

DockerHubにリポジトリを登録する

DockerHubに保存するため、新しいリポジトリを作成します。
docker commit build tkumazawa/ros:build と打ち込んで実行し、イメージを確認します。
tkumazawaは私のDocker HubのIDです。rosがリポジトリ名。buildがタグです。タグはver1.0などとしたほうがいいかもしれません。

command
> docker commit build tkumazawa/ros:build
> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tkumazawa/ros       build               2ff967da7a65        30 seconds ago      1.28GB
ros                 ros-build           2edba62b8053        22 hours ago        1.28GB

整ったらDockerHubにPUSHします。

command
>docker push tkumazawa/ros
The push refers to repository [docker.io/tkumazawa/ros]
8493815d0ca4: Pushed
372ede2259c3: Pushed
9e4af5cbf92b: Pushed
5d0ac2ca4dca: Mounted from library/ros
b0264d2ecd66: Mounted from library/ros
dc1e02c4e5b2: Mounted from library/ros
93928f93457b: Mounted from library/ros
95c9f2e4b310: Mounted from library/ros
5dfc22a79953: Mounted from library/ros
deb603bf064b: Mounted from library/ros
f5a315154171: Mounted from library/ros
55388b609b06: Mounted from library/ros
f55aa0bd26b8: Mounted from library/ros
1d0dfb259f6a: Mounted from library/ros
21ec61b65b20: Mounted from library/ros
43c67172d1d1: Mounted from library/ros
build: digest:

これでDockerで整えた環境をDockerHubに保存してバックアップすることができます。

実際にDocker+ROSで動かす方法はここを参考にしました。
Docker + ROS(kinetic)でチュートリアル

コンテナの削除がめんどくさい

やっているうちに大量のコンテナとイメージがメモリを圧迫しています。
ROSのコンテナが複数起動しているので、どうにもなりません。
で、「Docker実践入門」という本を教科書にしてますが、bashだと
docker rm $(docker ps -qa)で済むんですよね?
Windowsで同じことやろうとしたら、

command
#停止中コンテナの全消去
for /f "usebackq" %x in (`docker ps -aq`) do docker rm %x
#起動中コンテナも停止中コンテナも全消去
for /f "usebackq" %x in (`docker ps -aq`) do docker rm -f %x
#未参照のイメージを全消去
for /f "usebackq" %x in (`docker images -q`) do docker rmi %x

参考にしたのはこちら。
WindowsのDockerで溜まったコンテナやイメージを削除する

コンテナを消し終わったら、タグ付きでコミットしたイメージを消去。
怖いので一個ずつ消す。
docker rmi ros:ros-test
これやったら根っこから全部消える。もう一回、DockerHubからとってくるならOK。
docker rmi ros

VSCodeでDockerコンテナにリモート接続する

編集するときにいちいちエディタをコンテナにインストールするのが面倒だと思っていたらVSCodeにRemote Containersなる拡張を発見。
microsoft/vscode-remote-release

インストールして左下の隅っこをクリックするとメニューが開くので、Remote-Containers: Attach to running Container で接続したい対象を選択できます。
まず、先ほどDockerHubにpushしたイメージからコンテナを起動します。
docker run -it --name ros-wk tkumazawa/ros

image.png

先ほど立ち上げたros-wkを選択すると、新しいVSCodeのウィンドウが立ち上がるので、フォルダを選択して起動。
確かに中身が見えます。

GitHubからコンテナの中にリポジトリをcloneする

githubから編集中の自分のROSのパッケージをcloneします。
https://github.com/kumaxxp/ros_rc_package.git
これで、コンテナの中にgithubの内容を取り込んで編集できそうです。
ただし、GitHistoryやGitLensは無効で動きませんでした。なにか制限がかかっているようです。
VSCode標準のgit機能は問題なく使えます。githubへのpushもできますが、いちいちパスワードとIDを打ち込むのは面倒ですね。
かといってしょっちゅう生成と削除を繰り返す前提のコンテナイメージのssh-keyを登録するのもどうかと思いますので、その辺りは悩ましいところです。
とりあえずcatkin buildしてみます。

ROS
# catkin build
----------------------------------------------------
Profile:                     default
Extending:             [env] /opt/ros/melodic
Workspace:                   /root/catkin_ws
----------------------------------------------------
Build Space:        [exists] /root/catkin_ws/build
Devel Space:        [exists] /root/catkin_ws/devel
Install Space:      [unused] /root/catkin_ws/install
Log Space:          [exists] /root/catkin_ws/logs
Source Space:       [exists] /root/catkin_ws/src
DESTDIR:            [unused] None
----------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------
[build] Found '1' packages in 0.0 seconds.
[build] Updating package table.
Starting  >>> ros_rc_package
Finished  <<< ros_rc_package                [ 4.5 seconds ]
[build] Summary: All 1 packages succeeded!
[build]   Ignored:   None.
[build]   Warnings:  None.
[build]   Abandoned: None.
[build]   Failed:    None.
[build] Runtime: 4.5 seconds total.
[build] Note: Workspace packages have changed, please re-source setup files to use them.

とりあえず、パッケージは問題なくbuildできたみたいです。
pythonで記述したものは実行するとエラーが確実に出るのでここでは動かせない

ROS
# . ~/catkin_ws/devel/setup.bash
# rospack list
...
ros_rc_package /root/catkin_ws/src/ros_rc_package
...

setupの後、パッケージのリストを出力させると、パッケージは登録されていました。

続くかも

Dockerを使った機能の作成方法を、全部メモしてみました。
記述したコマンドをアレンジして使えば、とりあえずWindowsでDocker+ROS開発は問題なく実施できるかと思われます。

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

アラフォーのおっさんが一ヶ月でWebサービスを作った話

初めてWebサービスを作ってみました。
年末年始を使い、約1ヶ月程度で、どうにか公開までこぎつけられたので、振り返ってみたいと思います。

モチベーション

筆者は職業プログラマーではありませんが、将来に不安を感じ、プログラミングスキルを磨くことにしました。
「プログラマ35歳定年説」に言われる30代半ばを突き抜けた、まもなく40歳になるオッサンが、プログラミングスキルへ投資することに賭けたのです。

アラフォーになるまでの経験値

  • ユーザ系システムインテグレータに勤務
  • 数年前まではインフラ業務を担当(「VMware」とか)
  • 今は社内システム(バッケージソフトウェアで構築)の保守を担当
  • 数年前から深層学習(「TensorFlow」とか)の本を読み始めた

作り始める前(1ヶ月前)のレベル

  • 「jQuery」が少し分かる
  • 最近のWebシステムのトレンドって何?
  • フレームワークって何を使うといいの?「React」、「Vue」とか一杯あるけど
  • 「WebPack」?「Bazel」?何それ?
  • いつか「Docker」を使ってみたい
  • バックエンドはConcurrent(並行)処理に強い「Go」がいいらしい?

どんなWebサービスを作ったのか

手書き文字(カタカナ)の認識です。
深層学習ライブラリ「TensorFlow」を使った、「MNIST」等の手書き数字認識のカタカナ版になります。

[カタカナ道場]
https://katakanadojo.tokyo

si_1.pngsi_2.png

筆者には子供がいますが、この子の書くカタカナが怪しい。
(「シ」と「ツ」、「ソ」と「ン」が同じに見えるなど)

「コンピュータが読める字を書けた方がいいぞ!」とモチベーションを促し、字の上達につなげてもらう目論見で作りました。

※突貫工事で作ったので今後、手直ししていく予定です。メンテナンス中で落ちている場合があるのでご容赦ください。他人様に見せられる状態になったらソースコードもアップします。

まずは認識モデルを作る

画像認識の界隈では、「VGG-19」などの事前学習モデルを使った転移学習モデルが高精度の結果を出していますが、シンプルな畳み込み層だけで実装することにしました。

実際にご自身で試していただきたいと思いますが、雑に書いた字でも認識してくれるので、重厚なモデルは使わなくても十分かと考えます。
mo_1.png

得点は認識モデルが出力した確率を1万倍しています。
最初はパーセンテージで出力しようとしたのですが、小さい子にパーセンテージの概念は難しいようだったので整数にしました。

認識モデルが返すJSON出力はこんな感じです。

{
  predict: 'MO',
  top_3: [
    { label: 'MO', probability: 0.93235594 },
    { label: 'NE', probability: 0.05294613 },
    { label: 'SE', probability: 0.013120668 }
  ]
}

また、コンピュータにはどう見えているのかも興味深いです。
dora.png

トレーニングセットはETL文字データベースを使わせていただきました。
http://etlcdb.db.aist.go.jp/?lang=ja

Web化する

先述の認識モデルを作る際の言語は「Python」を使いました。
pythonでWeb化するには、ということで調べてみると、「Django」や「Flask」というWebフレームワークがあることがわかりました。
どちらも「WSGI」と呼ばれるインターフェースをベースにしているようなので、以下のパッケージを使って試しに書いてみました。

from wsgiref.simple_server import make_server

ここで疑問が

  • もっと速くできないか?
  • 認識モデルをメモリに常駐させておくとして、同時アクセスに耐えられるか?
  • フレームワークを使えばスレッドをうまく使ってくれるのか?

そうだ、「Go」にしよう

「TensorFlow」ライブラリは、「Python」以外の言語版APIも公開されているということで、「Go」版を調べてみました。
[TensorFlow Go API]
https://www.tensorflow.org/install/lang_go

Caution: The TensorFlow Go API is not covered by the TensorFlow API stability guarantees.

「安定性は保証しない」とあります。
これが企業の開発なら即刻、候補から外されるのでしょうが、個人の開発なので試してみることにしました。
「Go API」の詳細については、他の方が書いた記事をご覧ください。

[GoでTensorFlowのAPIを使ってみた話]
https://qiita.com/yasuno0327/items/8f8fa5629df3243347bd

結果は・・・速い。採用!!!

見た目をリッチにする

フロントエンドに着手します。
どのフレームワークを使うか、この辺の技術選定は本当に悩ましい。
筆者には遠回りしている時間がない。これから生き残るであろう技術を選びたい。
今回は「React」を使うことにしました。
理由はモバイル開発にもつなげられそうだと感じたからです。

バックボーンや目的によって違ってくるかと思います。他の方が書いた記事をご覧ください。

[ReactとVueのどちらを選ぶか]
https://qiita.com/yoichiwo7/items/236b6535695ea67b4fbe

「Material-UI」といった「UIフレームワーク」が公開されているので活用させていただきました。
クライアント側は、画像をBase64エンコードして、Ajax通信でサーバ(Goで実装)にPOSTします。

VPSを借りる

「create-react-app」コマンドで「React」アプリを作り、それをbuildすると、画面に「ZEIT Now」を紹介する出力が出てきます。

https://github.com/zeit/now

Webのフロント部分だけなら、「Zeit Now」でいいと思いました。
ドメイン、証明書まで付いていて無料。すごい。

しかし、今回は「TensorFlow」のモデルを動かすので、ある程度のリソース(CPU、メモリ)は確保したい。

NTTPC社が提供するVPSサービス「WebARENA」を使うことにしました。
https://web.arena.ne.jp/indigo/

メモリ1GBプラン、月額349円(税込)をチョイス。
「1vCPU」、「1GBメモリ」、OSは「CentOS」か「Ubuntu」を選択可能。

この辺はVPSサービスから探し始めて、わりと直感的に決めてしまった面があり、「AWS」や「Azure」といったクラウドサービスは検討していません。
時代はパブリッククラウドの流れにあるし、後になって検討すべきだったと悔いるかもしれません。でも、いいのだ。

コンテナ化する

「Ubuntu」上に「Docker」エンジンを入れます。
Dokerホストが1台だけなので「kubernetes」は無し。
(「kubernetes」がどんなものなのか興味はありましたが、今回はパス)
下記3つのコンテナを立てました。

  1. HTTPS化、証明書周り(「https-portal」)
  2. リクエストを振り分けるリバースプロキシ(「Node.js」)
  3. Base64エンコードされた画像を認識し判別結果をJOSNで返す(「Go」)

図にすると以下のようなイメージになります。
1vCPU、1GBメモリのゲストOS上で動いていることに驚嘆します。
katakanadojo_構成図.png

ドメインを取る

「ムームードメイン」で、1年契約の「katakanadojo.tokyo」を取りました。
消費税込みで「110円」でした。
「お名前.com」と「ムームードメイン」の2つを見て、安い方にしました。

かかった費用

VPS利用料が毎月349円、ドメイン契約料が毎年発生するして、ランニング費用は月額500円を切るといったところでしょうか。
個人で容易にサービスを公開できる時代になったと感じます。
このサービスをいつまで維持するかは未定です。

終わりに

ざっと振り返った流れは以上になります。
一ヶ月前のことなのに忘れかけている部分も多く、せっかく苦労して乗り越えた部分を残せていないと感じました。
もし興味を持っていただける方がいらっしゃいましたら、詳細を加筆していきたいと思います。

最後まで読んでいただき、ありがとうございました。

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

Dockerで作成したNetwork Namespaceへアタッチする

Dockerのデフォルト・ネットワーク(bridge)では、コンテナを作成するたびにNetwork Namespaceが作成される。
しかし以下コマンドを実行するだけでは取得する事ができない。

$ sudo ip netns ls

ip netns は/var/run/netns 配下のファイルを一覧表示する実装になっているが、
Docker経由でNetwork Namespaceを作成した場合はこのディレクトリ配下にファイルが作成されない(というかこのディレクトリ自体作られない)。
そのため以下手順を実行する必要がある

$ sudo mkdir /var/run/netns
$ pid=$(docker inspect $CONTAINER_ID --format '{{.State.Pid}}’)
$ sudo ln -s /proc/${pid}/ns/net /var/run/netns/[任意のファイル名]

作業ログ

[ec2-user@dockerHost ~]$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
71de02f377ed        busybox             "sh"                45 minutes ago      Up 45 minutes                           c1
[ec2-user@dockerHost ~]$ ip netns list
[ec2-user@dockerHost ~]$ 
[ec2-user@dockerHost ~]$ CONTAINER_ID=71de02f377ed
[ec2-user@dockerHost ~]$ pid=$(docker inspect ${CONTAINER_ID} --format '{{.State.Pid}}')
[ec2-user@dockerHost ~]$ sudo mkdir /var/run/netns
[ec2-user@dockerHost ~]$ sudo ln -s /proc/${pid}/ns/net /var/run/netns/tmp-container-ns
[ec2-user@dockerHost ~]$ sudo ip netns ls
tmp-container-ns (id: 0)
[ec2-user@dockerHost ~]$ sudo ip netns exec tmp-container-ns bash
[root@dockerHost ec2-user]# 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

xysfdx+dockerでSalesforce開発環境構築

xysfdx+dockerでSalesforce開発環境構築

必要なものをインストールする

xysfdxでdocker images と docker containerが作成できるから、手動でコマンドの発行が不要。 デフォルトショットキー:ctrl+shift+j

pull images

pull images : docker: pull image exiasfdc/sfdx

xysfdx-docker-image

create container

create container : docker: create sfdx container

xysfdx-docker-container

use docker shell

use docker shell : docker: attach docker shell

xysfdx-docker-bash

おめでとうございます、 xysfdxのSfdx Docker開発環境構築完了しました。

注意点

  • 現時点で force:auth:web:login or force:auth:web:login:setdefaultusernameがwindowsのdocker環境で使えませんから、xy:auth:username:login を使って認証してください。
  • xy:auth:username:loginexiahuang/sfdx-xy-pluginプロジェクトのコマンドです、すでにdocker image exiasfdc/sfdx に含みます。
  • dockerモードでxysfdxの force:project:createコマンドが発行できません、手動でプロジェクトを作成お願いします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker for Windows で Kubernetesが起動しないときのトラブルシューティング

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

0. 始めに

社内でKubernetesの勉強会をしたのですが、その時にKubernetesサーバーを立てるのも大変だったので、Docker for WindowsのKubernetesを使おうと言うことになり、複数の人にWindows10へDocker for Windowsを入れてもらい、Kubernetes機能を有効にしたのだけど、Kubernetes機能がいつまで経っても起動してこない人がいた(私です)ので、トラブルシューティングしてみました。

1. Docker for Windowsのインストールについて

以下をご参照ください。

Docker for WindowsでKubernetesを試してみる - Qiita
https://qiita.com/h-r-k-matsumoto/items/68f694650029ddf7351d

Dockerのトラブルシューティングについては以下をご覧ください。
Windows10 × Docker for Windows トラブルシューティング - Qiita
https://qiita.com/takeru08ma/items/7878a293c55a9902f404

2. インストールしたバージョン

image.png

Windows OSのバージョン
image.png

3. 状況

下のDockerとKubernetesで、Kubernetes側がいつまで経ってもオレンジでした
(以下の画像は動くようになった時のステータスです)
image.png

Hyper-VマネージャーもずっとCPU使用率が0%でした。
(以下の画像は動くようになった時のステータスです)
image.png

4. 対応策

3日ほど放っておいても改善しないのでググってみました。
以下を見つけました。

Unable to start kubernetes on docker desktop win 10 pro · Issue #3799 · docker/for-win
https://github.com/docker/for-win/issues/3799

どうも、以前Docker for WindowsでKubernetesを動かしたことがある人の固有の問題のようです。

C:\Users<Windowsアカウント>.kubeフォルダー

C:\ProgramData\DockerDesktop\pki
が関係しているらしく、中を見ると
.kubeフォルダー
image.png

pkiのフォルダー
image.png
のようになっていました。

Kubernetesを構築したことがある人はピンとくると思いますが、各種Kubernetesのサービス用のサーバー証明書が入っています。

pkiフォルダーを削除します。
タスクトレイのDockerから「Restart」を選択してDockerを再起動します。
image.png

動き出しました。
image.png

5. 原因

Hyper-Vで動くKubernetesの仮想サーバーで使うTLSの鍵情報を新しい鍵情報を作ろうとしていたが、以前インストールした時のものが残っていてDocker for Windowsはデフォルトでは上書きしない為、いつまで経っても起動しなかった。

ということのようです。

6. まとめ

Happy, Kuberneting!

WSL2が待ち遠しいです。

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

Pytorch+JupyterLab+GPUをDockerで作成

ぐぐりながら見様見真似でdockerを使ってみました。

目的

結果

初めはjupyterのdocker-stacksのベースを書き換えたりして試行錯誤してましたが、公式のpytorch/pytorchをベースにjupyterlabなど必要なライブラリをインストールすることで目的のものができました。

環境

Dockerやnvidia-container-toolkitはインストール済みとします。
- GPU: GTX1080
- OS: Ubuntu 18.04.3 LTS
- Nvidia driver: 440.48.02 CUDA Version: 10.2
- Docker: 19.03.5

手順

適当な作業用フォルダを作成し移動

$ mkdir pytorch-lab[なんでも良い]
$ cd pytorch-lab

Dockerfileを作成

$ vim Dockerfile
Dockerfile
FROM pytorch/pytorch:latest

# Install required libraries
RUN conda config --add channels pytorch \
 && conda config --append channels conda-forge \
 && conda update --all --yes --quiet \
 && conda install --yes --quiet \
    ipywidgets \
    jupyterlab \
    matplotlib \
    nodejs \
    opencv \
    pandas \
    scikit-learn \
    seaborn \
    sympy \
 && conda clean --all -f -y

# Install jupyter extensions
RUN jupyter nbextension enable --py --sys-prefix widgetsnbextension \
 && jupyter labextension install @jupyter-widgets/jupyterlab-manager

COPY jupyter_notebook_config.py /root/.jupyter/

やっていることは

  • base imageとしてpytorch/pytorchを使用。
  • そのままconda updateを行うとpytorchがダウングレードされてしまうので、conda config --add channels pytorchでpytorchのライブラリを高優先度で追加。
  • condaのライブラリだけだと足りないことがあるのでconda config --append channels conda-forgeでconda-forgeのライブラリを低優先度で登録。
  • 必要なライブラリのインストール。
  • jupyterlabでtqdmでの進捗バー表示が行えるようにjupyterlabの拡張機能をインストール。
  • 後述するjupyterの設定ファイルをコピー。

jupyterの設定ファイルを作成。

Dockerfileと同じ場所にjupyter_notebook_config.pyを作成。

私は試行錯誤していた際に使用したjupyter/docker-stacks/base-notebook/jupyter_notebook_config.pyをコピーして設定を書き加えています。
追加した設定は

  • c.NotebookApp.allow_root = True : rootでの起動を許可
  • c.NotebookApp.password = 'パスワードのハッシュ値' : ログインパスワードを設定

パスワードのハッシュ値はローカルのpythonにipythonがインストールされていれば、以下のコマンドで生成できます。

$ ipython

In [1]: from IPython.lib import passwd
In [2]: passwd()

パスワードを設定して表示される'sha1:~'をコピーしておいてください。

jupyter_notebook_config.py
c.NotebookApp.allow_root = True
c.NotebookApp.password = 'sha1:~'

これらをc.NotebookApp.open_browser = Falseの後ろあたりに打ち込んでください。

imageのビルド

上記のDockerfileおよびJupiter_notebook_configのあるフォルダでビルドを行います。
pytorch-labのところはわかりやすい任意の名前をつけてください。
初回はベースのpytorch/pytorchのダウンロードが行われるのでしばらく時間がかかります。

$ docker build -t pytorch-lab ./

docker imagesで作成したイメージが追加されていたら成功です。

$ docker images
REPOSITORY              TAG                      IMAGE ID            CREATED             SIZE
pytorch-lab             latest                   bd952fdf9b43        12 seconds ago      6.15GB
pytorch/pytorch         latest                   37b81722dadc        9 days ago          4.16GB

起動方法

/home/[ユーザー名]/ML/にデータを保存するとします。

$ docker run -d --rm --gpus all -v ~/ML:/workspace -p 8888:8888 --name pytorch pytorch-lab jupyter lab

オプション
-d バックグラウンドで実行
--rm コンテナ終了時にコンテナを削除
--gpus all コンテナでGPUを使用可能にする
-v ~/ML:/workspace ローカルの~/MLをコンテナの/workspaceにマウントして作成したファイルが保存されるようにする。
-p 8888:8888 ローカルのポート8888への接続をコンテナの8888(jupyterlab)へ送る。
--name pytorch コンテナに任意の名前をつける。

使い方

ブラウザからhttp://localhost:8888/に接続、ログインページが表示されるので設定したパスワードでログインする。

スクリーンショット 2020-01-26 2.53.24.png

問題点

  • pytorchのイメージもライブラリもバージョンを指定せずビルドの度に最新のものがインストールされるので、今後のアップデート次第では作ったイメージがうまく動作しない可能性がある。
  • rootでjupyterlabを起動するのはセキュリティ的にどうなんだろう(SSHポートフォワードを前提にはしている)。
  • tqdmの表示はうまくいくが、torch vision.datasets.MNISTなどのダウンロード時の進捗バーは正常に表示されない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む