20200524のdockerに関する記事は20件です。

Docker Hubの使い方

環境

macOS 10.15.4
Docker 19.03.8

アカウントの登録

下記のリンクからDocker Hubのアカウント登録を行います。
https://hub.docker.com

dockerhub01.png

Docker Hubを使う

Docker Hubにログインする

ターミナルから指定のディレクトリに移動してDocker Hubと連動させるためログインを行います。

$ docker login

するとUsenameとPasswordが求められるのでDocker Hubのアカウント登録した情報を入力します。

$ docker login
Username:(アカウント名) 
Password:(パスワード)
Login Succeeded

これでDocker Hubとの連動が完了しました。

イメージIDを調べる

下記のコマンドを実行してイメージIDを調べます。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
recipegram_web      latest              a91018b6cf9c        7 days ago          1.3GB
<none>              <none>              1f63874cf252        7 days ago          1.3GB
<none>              <none>              38f311130abd        7 days ago          1.04GB
docker_sample_web   latest              604c94f14094        8 days ago          1.04GB
<none>              <none>              a1cd1b5bdb2a        8 days ago          989MB
ruby                2.5                 a98425292e84        4 weeks ago         843MB
postgres            latest              0f10374e5170        4 weeks ago         314MB
gihyodocker/echo    latest              3dbbae6eb30d        2 years ago         733MB

指定のイメージIDを探して下記のように記述します。

アップロードを実行する

$ docker tag a91018b6cf9c chisaki0606/recipegram:latest 

この記述はわたしの場合の例ですが、a91018b6cf9cは指定のイメージIDになります。
そしてchisaki0606/recipegram:latestの記述は(Docker Hubのアカウント名)/(リポジトリ名):(タグ名)になります。最後のlatestは指定はありませんが最新の場合にはこちらのタグ名にすることが慣例になっています。

確認をするとアップロードが完了されました^_^
スクリーンショット 2020-05-24 22.13.10.png

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

Docker logs をgrepする

コンテナのログは、標準エラー出力 (stderr)に記録されます。

一方、「|」で記述するパイプラインは、標準出力(stdout)で機能します。

コンテナのログをパイプラインで受け取れるように、
標準エラー出力標準出力へと出力先を2>&1で変更します。

これで、パイプ後のgrepコマンドが動くようになります。

docker logs app 2>&1 | grep "test"

ちなみに、2>&1を省略した形として、次のように記載することもできます。

docker logs app |& grep "test"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Docker】使ってないやつらを葬り去る

内容

pruneコマンドのメモです。

image

docker image prune

dangling

dangling(ダングリング;宙ぶらりんな状態)なイメージ (ブール値: true か false )
images — Docker-docs-ja 17.06.Beta ドキュメント より引用

つまり、タグ付けされていないイメージをさします。

オプション

--all , -a 使っていない(containerとして起動していない)imageを全て削除
--filter filterをかけることができる (例: until=)
--force , -f 確認してこなくなる

Dockerのあれこれを断捨離する - Qiita

container

docker container prune

network

docker network prune

volume

docker volume prune

system

docker system prune

停止中のコンテナ、ボリューム、イメージ、ネットワークを全て削除します。

参考にした記事

docker image prune | Docker Documentation
Docker一括削除コマンドまとめ - Qiita
Dockerで不要なコンテナとイメージを削除する - Qiita

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

Docker for Mac の Mutagen-based caching で Volume のパフォーマンスが劇的に改善した

Docker for Mac の Edge channel で、 Mutagen ベースのキャッシュが使えるようになっています。(手元のバージョンは 2.3.1.0)

従来、 EC-CUBE をはじめとする Symfony をベースとしたアプリケーションや、Composer や npm などのパッケージ管理システムのファイルをマウントすると、強烈に遅くなる問題がありました。

今回利用できるようになった Mutagen ベースのキャッシュを利用するには、

  1. Preferences -> Resources -> FILE SHAREING でマウントするディレクトリを指定
  2. キャッシュを ON にするだけ。

です。
スクリーンショット 2020-05-24 19.54.49.png

あとは通常通り、アプリケーション全体をボリュームにマウントして大丈夫です。

## 例
docker run --name ec-cube -p "8080:80" -v "$PWD:/var/www/html:cached" --link container_mysql:db eccube-php-apache

以下、手元の環境での比較です。
約7倍にパフォーマンス向上しています。
(性能のよいディスク使っているので、体感的な差は少ないですが、古めの環境では大きく差が出ると思います)

Mutagen-based caching OFF の場合
スクリーンショット 2020-05-24 20.24.55.png

Mutagen-based caching ON の場合
スクリーンショット 2020-05-24 20.21.49.png

GitHub の issues にもパフォーマンス検証結果がコメントされていますので、併わせてご覧ください。

Ruby や Node.js など、 PHP 以外のアプリケーションでもパフォーマンス向上が期待できます。
Docker for Mac の遅さに手を焼いていた方はぜひお試しください!

2020年5月26日追記

マウントしたファイルのパーミッションが変わってしまう問題 があります。
近いうちに改善されるかもしれませんが、 コンテナ上で chmod -R o+w <mounted volume> するなりして凌ぎましょう...

こちらのツイートも参考に

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

Docker Network とは何ぞ?

ずっとDockerを使っていますが、あまりDockerNetworkを意識することが今までなく、役割とかいまいちよくわかっていないので、調査して、自分用のメモを残します。

ドキュメントはここを読みました。

Docker Networkとは

Dockerのネットワークを管理するものです。
Dockerをインストールすると、自動的に3つのネットワークを作成します。
確認するコマンドは

$ docker network ls

NETWORK ID          NAME                DRIVER
7fca4eb8c647        bridge              bridge
9f904ee27bf5        none                null
cf03ee007fb4        host                host

確かに設定してあります。

bridgeネットワーク

ホスト側には、docker0 というブリッジができています。これがbridgeネットワークと繋がっています。
名前からして、ブリッジ接続でホストのネットワークと繋がっていると思われます。
確認は下記のコマンド

$ ifconfig

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:dc:ab:d1:d4  txqueuelen 0  (イーサネット)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

コンテナに接続するネットワークは --netのオプションで設定できます。
例えば、

$ docker run -d --name container1 --net bridge busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"

ような感じです。
何も指定しない場合、デフォルトのネットワーク bridgeが選択されます。

デフォルトのネットワークはbridgeですが、他のものはどういうものなのか。

noneネットワーク

noneを指定するとネットワーク・インターフェースが欠如した状態でコンテナを作れます。

例えば、

$ docker run -d --name container2 --net none busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"

でコンテナを作る。
確認は下記のコマンド

$ docker exec container2 cat /etc/hosts

127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

$ docker exec container2 ifconfig

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

ループバックインターフェースしかないですね。

ちなみにbridgeネットワークで作った場合は、

$ docker exec container1 cat /etc/hosts

127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  ba703c0e2904

$ docker exec container1 ifconfig

eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:76 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:11028 (10.7 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth0のネットワークインターフェースがありますね。

hostネットワーク

hostネットワークは名前の通り、ホスト側のネットワーク・スタックにコンテナを接続しており、
コンテナ内のネットワーク設定が、ホスト上と同じに見えます。

$ docker run -d --name container3 --net host busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"

$ docker exec container3 cat /etc/hosts

127.0.0.1   localhost
127.0.1.1   --
127.0.2.1   --

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

$ docker exec container3 ifconfig
※ホストでifconfigを使った時と同じ出力

これは結構便利ですね。

ブリッジ・ネットワークの詳細

下記のコマンドで詳細を見ることができます。

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "e37815cd479e4272ea69f16c54b55fdf41ecb35151c1421a3b4bd2c16a46c34f",
        "Created": "2020-05-17T17:11:01.385296653+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "ba703c0e2904404891295f707c3b323a48ee01631e8082948038478c3fe89990": {
                "Name": "container1",
                "EndpointID": "51244eaedf829aea7887272f28bf7aeb61573b14894d304c7af215c0dbb4c13f",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

自動的にサブネットやゲートウェイが作られていて、それを見ることができます。
接続しているコンテナの情報も見れます。

bridgeネットワークのコンテナにpingで接続確認をします。

$ docker exec container1 ping -w3 172.17.0.2docker exec container1 ping -w3 172.17.0.2

PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.042 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.045 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.122 ms

--- 172.17.0.2 ping statistics ---
4 packets transmitted, 3 packets received, 25% packet loss
round-trip min/avg/max = 0.042/0.069/0.122 ms

コンテナ→ホストは繋がっていることがわかりますね。

カスタムネットワークを作る

下記のコマンドでユーザ独自のネットワークを作れます。

$ docker network create --driver bridge new_nw

$docker network inspect new_nw
[
    {
        "Name": "new_nw",
        "Id": "129f288d936696f13caa17580e7c12f94d58e13d135e6eeb1662c1cdb85e0c73",
        "Created": "2020-05-24T18:19:00.890438557+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

この新規に作ったネットワークはbridgeのネットワークとは、独立しているので、
このネットワークにつなぐコンテナは、他のコンテナと独立することができます。
逆に、同じネットワークにすれば、他のコンテナと連携ができます。非常に便利ですね。

オーバレイ・ネットワーク

まず、オーバーレイネットワークという用語を聞いたことなかったので、確認。
「オーバーレイネットワークとはあるネットワークの上に構築された別のネットワークのこと」ということを指す模様
インターネットVPNやP2Pネットワークもオーバーレイネットワークのようで、SDNの一方式として使われるようです。

Dockerを使ったオーバーレイネットワークですが、ドキュメントを見ると、どうやら※VXLANをDockerNetworkで作れるようです。

※VXLANは私自身は情報処理試験で知識としてしかわかってなく、異なるネットワークを、仮想的に同一のネットワークとして通信ができるものくらいの理解です。

ここは他者様のサイトを参考
これにより、異なるネットワークのコンテナ同士で、通信ができるようになります。

カスタム・ネットワーク・プラグイン

必要があれば、自分自身でネットワーク・ドライバ・プラグインを書けます。
書き方は、ここここ

作成したネットワークを元に、派生してネットワークを作ります。

$ docker network create --driver weave mynet

 

参考

おうちで学べるネットワークのきほん
 わかりやすい

ブリッジ接続
 このサイトもすき

Docker_VXLAN
 図がわかりやすい

VXLAN詳細

ネットワークの復習もできて、ちょっと調べて得しました。

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

超基礎からの 速習 Docker (3)

Whale, Docker

本稿は、Christffer Noring さん (@chris_noring) の Learn Docker, from the beginning, part III を翻訳し、分かりやすいように少しだけ追記、サンプルコードの実行上の補足等を行ったものです。シリーズ翻訳の意図については 超基礎からの 速習 Docker (1) の冒頭に掲載しています。併せてご参照くださいませ。

超基礎からの 速習 Docker シリーズ一覧

TLDR; とても長いけど、誓って、ここにあるのが最小限なんです。中盤で苦痛を伴うけど、きっと僕らは勝利する:smiley:

  • 超基礎からの 速習 Docker (1)
    • なぜ Docker なのか、コンテナーやイメージ、Dockerfile の基本コンセプトの解説、もちろん、それらを管理するのに必要なコマンド群もカバーしています。
  • 超基礎からの 速習 Docker (2)
    • Volume を用いたデータの永続化や、開発環境の Volume 化を通じて、開発をより手軽なものにします。
  • 超基礎からの 速習 Docker (3)
    • いまここ。
  • 超基礎からの 速習 Docker (4)
    • Docker Compose を用いた複数サービスの管理方法を解説します(その1)
  • 超基礎からの 速習 Docker (5)
    • Docker Compose を用いた複数サービスの管理方法を解説します(その2)

本稿はシリーズ パート3 です。このパートでは、データベースと Docker がどのようにお互い動作するのかについて学ぶことにフォーカスします。また、コンテナ環境のデータベースと強く結びつける Link 機能のコンセプトについても解説しています。

本稿では以下のトピックをカバーしています。

  • MySQL 実行に関する基本についてカバー データベース一般の基本をカバーすることは常に良いことで、本稿では、その一つとして MySQL を選択しています。
  • なぜ MySQL Docker イメージを使う必要があるのか どのようにイメージからコンテナーを生成するか、動作させるために必要な環境変数についても説明します。
  • MySQL コンテナーに接続する方法 Link 機能を使ったアプリケーション コンテナーから、二つのコンテナー間の基本的な Link 機能をどのように実現するか、データベースの初期設定を定義する際、どのような利点に使用できるかについてです。
  • Link 機能の知識を広げる コンテナーを Link する新しい方法をカバーします。Link には 2種類の方法があります。一方の方法がよく使われ、他方は非推奨となっているため、僕らは新しい方法をカバーします。
  • データベースを管理する良い方法を説明 初期構造や初期データ(シード データ)を与える方法です。

リソース

Docker を使う事、コンテナー化は、一枚岩をマイクロサービスに分解していくことです。このシリーズのいたるところで僕らは Docker やそのコマンド体系をマスターするために学ぶことになります。そうすれば、きっと君は自作のコンテナーをプロダクション環境で使いたくなるでしょう。その環境は大抵クラウド上にあります。十分な Docker 経験を積んだと思ったなら、次のリンクで Docker をクラウドでどのように活用できるか、ご確認してみると良いと思います。

  • Azure 無料アカウントのサインアップ プライベート レジストリのようなクラウドのコンテナーを使うには、無料 Azure アカウントが必要でしょう。
  • クラウドのコンテナー クラウドのコンテナーについて他に知っておくべきことについて網羅する概要ページです。
  • 自作コンテナーをクラウドにデプロイ 今の Docker スキルをレバレッジしてクラウド上でサービスを動かすことがいかに簡単かを示すチュートリアル。
  • コンテナー レジストリの作成 自作 Docker イメージを Docker Hub に入れられますが、クラウドのコンテナー レジストリも可能です。自作イメージをどこかにストアして、一瞬でレジストリから実際のサービスをできるようにすることは凄くないですか?

データベース一般、とりわけ MySQL を使うには

データベース一般について、僕らは以下のようなことをやりたくなります:

  • read 僕らは様々な Query の方法でデータを読みたいと思います。
  • alter/create/delete 僕らはデータを変更する必要があります。
  • 構造を追加する 僕らは table や collection と言った構造を作成する方法が必要です。それにより、特定フォーマットでデータは保存されます。
  • 初期データ(シード データ)の追加 シンプルなデータベースでは全く不要でかも知れませんが、複雑なシナリオの場合、table が基本データで事前入力されている必要があるかも知れません。表示状態を作るためや、既に存在するデータ、またはある状態に入るデータと言った、異なるシナリオのテストを容易にするため、開発フェーズではシード データが重要です。例えば、ショッピング カートにテストしたいアイテムが入っている状態で、会計ページをテストしたい時です。

インデックスの追加や、アクセス権の異なるユーザーの追加などなどなど、データベースで行いたいことは山ほどありますが、僕らが Docker を使う上で知るべきリファレンスとして、上記 4つのポイントにフォーカスしましょう。

インストールと MySQL への接続

MySQL をインストールする方法はたくさんありますが、全部が全部早いわけではありません:confused:。Linux の場合は以下のようにタイプするのも簡単でしょう:

sudo apt-get install mysql-server

訳注
Linux と言ってもディストリビューションとか環境によって MySQL のインストール方法はマチマチでしょうけど、恐らく Linux ユーザーなら各々 MySQL のインストールはできますよね・・?:sweat_smile:

Mac の場合、brew を使って次のように代わりにタイプするでしょう:

brew install mysql

訳注
上記方法で Mac に MySQL をインストールするには、Homebrew をインストールする必要があります。インストール方法などの詳細は以下を参照くださいませ。ターミナルから一行たたくだけです。
https://brew.sh/index_ja

他のシナリオの場合でも、インストーラーをダウンロードして Wizard に従ってください。

Windows の場合、訳者の環境では XAMPP と言う、Apache + MySQL + PHP を自動でインストールするものを利用してしまいました。もちろん、MySQL 単体インストールも可能のようです。いずれにしても、PowerShell からインストールする方法はありませんので、各手順にある通り、インストーラーをご利用ください。

一旦、MySQL をインストールし終わると、以下のような情報が出てきます。もちろん、インストール パッケージによって異なるでしょう:

==> mysql
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start

上の例では、root パスワードがまだついてないって言ってます・・ギャー!。しかし、mysql-secure-installation を実行することで fix できます。今はとりあえず、提案されている通り mysql -uroot を実行してデータベースに接続しましょう。

% mysql -uroot
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

NOOO、何が起きたんだ?インストール時に表示された画面でこの情報を得ましたが、brew services start mysql を実行して、MySQL を起動する必要があるのでした。OK、さっそく brew services start mysql を入力しましょう:

% brew services start mysql
==> Tapping homebrew/services
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-services'...
remote: Enumerating objects: 40, done.
remote: Counting objects: 100% (40/40), done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 731 (delta 10), reused 27 (delta 6), pack-reused 691
Receiving objects: 100% (731/731), 201.74 KiB | 470.00 KiB/s, done.
Resolving deltas: 100% (282/282), done.
Tapped 1 command (40 files, 277.3KB).
==> Successfully started `mysql` (label: homebrew.mxcl.mysql)

一番最後、Successfully started `mysql`:
Alright, Alright, Alright

Matthew が正しいかどうか見てみよう(訳注:gif が Matthew David McConaughey?)接続できたかな?

訳注
Windows でも MySQL Server を起動しなくてはいけない場合があります。Linux はもちろんですね。Windows で、MySQL 単体インストール手順に従った場合は、サービスとして自動起動するようなので、特に起動しなくても大丈夫なのではないかと想像します(ごめんなさい、未検証)XAMPPを使っている場合、XAMPP Control Panel を使って MySQL を起動してくださいませ。
XAMPP Control Panel
しかし、MySQL Server を起動しなければならない、ということは使ったことある人なら常識ですよね。全般、この章の MySQL 解説はちょっと丁寧すぎる感じもしてますけど、以降もいろいろハマりながら進めるために、基礎を一度再確認しておくと良い、ということなのでしょう。

% mysql -uroot             
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.19 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

プロンプト mysql> を得ることができた。僕らは入れた:smile:

OK、パスワードなしで接続していたので、それを Fix しましょう。まだデータベースを持ってなかった。これも Fix しよう:smiley:

僕らがデータベースを持っていないというわけでもなく、自分でデータベースを作っていない、が正くて、僕らがタッチできない実行サポート用データベースはあります:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

次に新しいデータベースを作成、選択します。次のように Query を入力します:

mysql> CREATE DATABASE Customer;
Query OK, 1 row affected (0.01 sec)

mysql> USE Customer;
Database changed
mysql> 

OK、素晴らしい。でも待って。僕らはテーブルを持ってなくないか?そうそう、僕らはテーブルをどうにかして作らないといけない。ターミナルからテーブルを作ることもできるけど、ちょっと痛い。複数のステートメントがたくさん出てきます。ですので、もしできるなら MySQL にファイルでデータベースと作りたい全てのテーブルを入力しましょう。テーブルを追加し続ける最初のファイルを定義しましょう。

database.sql
/* creates a table `tasks` */
CREATE TABLE IF NOT EXISTS tasks (

task_id INT AUTO_INCREMENT,

title VARCHAR(255) NOT NULL,

start_date DATE,

due_date DATE,

status TINYINT NOT NULL,

priority TINYINT NOT NULL,

description TEXT,

PRIMARY KEY (task_id)

);
/* add more tables below and indeces etc as our solution grows */

OK、データベース構造のファイルを作ったので、その内容を取得するため、次のようにして source コマンドを使うことができます:

mysql> source /Users/・・・/database.sql
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW TABLES;
+--------------------+
| Tables_in_customer |
+--------------------+
| tasks              |
+--------------------+
1 row in set (0.00 sec)

mysql> 

もし、君の database.sql ファイルのあるフルパスを知りたければ、君のファイルのある場所で pwd とタイプします。そして、source [path to sqlfile]/database.sql とタイプします。先に示した通り、SQL ファイルを実行する前に、データベースを選択する必要があります。テーブルが作成されたかどうかは SHOW TABLES; で確認します。同じコマンドを使ってデータベースにシードデータを入れることもできますが、CRWATE TABLE ではなく、INSERT ステートメントになっている sql ファイルを処理することになります・・

OK、では、MySQL はこれで十分。次は Docker の中で動く MySQL について話そう。(訳注:MySQL のコンソールからは、quit; などとして抜けてくださいませ)

なぜ MySQL Docker イメージが必要で、どのようにコンテナーとして起動・実行するのか

OK、それでは、アプリケーション用のコンテナーが欲しいとしましょう。更に、そのソリューションにはデータベースが必要だとしましょう。コンピューターが実行されているホストに MySQL をインストールすることはあまり意味がないでしょう。コンテナーのマントラの一つは、コンテナーが実行されているホスト システムについてケアする必要はない、という意味です(訳注:なぜマントラなんていう文教用語が出てきたのか分かりませんが、要はコンテナーで考えている時、ホストを考慮する必要はない、ということのようです)OK、なので、コンテナーに入っている MySQL が必要なのです。アプリがコンテナーを所有するのでしょうか。それとも、コンテナーを分離するのでしょうか。いい質問です。アプリに MySQL をインストールすることもできますし、別のコンテナーで MySQL を実行することもできます。その論拠は:

  • ローリング アップデート これによって、アプリケーションが個別にリスタートしている間も、データベースは常にオンラインになり、ダウンタイムが発生しません。
  • スケーラビリティ 疎結合でノードを追加してスケールすることができます。

これに対してはたくさんの議論・意見のあるところなので、どれが良いかは君だけが知ってます・・君のやり方でやるのが良いよ:smiley:

スタンドアロン イメージとしての MySQL

MySQL のイメージを引っ張ってくるシナリオについて話しましょう。OK、一歩ずつ手順を追って、説明しましょう。最初に行うことは MySQL を実行してみることです。前章で学んだようにイメージを持っていなければイメージを引っ張ってきます。コマンドは次のようになります:

docker run --name=mysql-db mysql

OK、アウトプットはどうなっているでしょう?

% docker run --name=mysql-db mysql
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
afb6ec6fdc1c: Pull complete 
0bdc5971ba40: Pull complete 
97ae94a2c729: Pull complete 
f777521d340e: Pull complete 
1393ff7fc871: Pull complete 
a499b89994d9: Pull complete 
7ebe8eefbafe: Pull complete 
597069368ef1: Pull complete 
ce39a5501878: Pull complete 
7d545bca14bf: Pull complete 
211e5bb2ae7b: Pull complete 
5914e537c077: Pull complete 
Digest: sha256:a31a277d8d39450220c722c1302a345c84206e7fd4cdb619e7face046e89031d
Status: Downloaded newer image for mysql:latest
2020-05-24 02:36:17+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.20-1debian10 started.
2020-05-24 02:36:17+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2020-05-24 02:36:17+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.20-1debian10 started.
2020-05-24 02:36:17+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
        You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

イメージを引っ張ってこれましたね(訳注:英語では pull down)アァァァンド、エラー。

僕らは間違ってばかりだ:frowning:

データベースが初期化されていない、パスワード オプションが指定されていない、などなど。これを Fix していきましょう:

docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=complexpassword -d -p 8001:3306 mysql

そして勝者は:

% docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=complexpassword -d -p 8000:3306 mysql
docker: Error response from daemon: Conflict. The container name "/mysql-db" is already in use by container "3069364970cd5a876976180a89b30a51e41ae003f0ae75165c30d1d183694332". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.

うげっ、エラーメッセージを出したにも関わらず、僕らが前に始めたコンテナーが起動・実行されている。OK、コンテナーを落としましょう。

docker rm mysql-db

上記のようにデータベース セットを再度実行しましょう。

% docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=complexpassword -d -p 8001:3306 mysql
c352b4abe3adcb8af5f3155093d69ae85d8540cbc66cc780b55b0a047288aa73

OK、全てのログはターミナルに表示されません。なぜなら、Daemon モード(訳注:Detached モードが正しい?)で実行されているからです。docker ps を実行して確認しましょう:

% docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
c352b4abe3ad        mysql               "docker-entrypoint.s…"   45 seconds ago      Up 44 seconds       33060/tcp, 0.0.0.0:8001->3306/tcp   mysql-db

この時点で、外側から接続したくなります。ポート フォワーディングで 0.0.0.0:8001 に接続する必要があります:

mysql -uroot -pcomplexpassword -h 0.0.0.0 -P 8001

訳注
Windows では 0.0.0.0 にアクセスすることはできませんでした。そもそも 0.0.0.0 を宛先にするのは誤りだ、という意見もあるようです。ここでは単に MySQL が動いていることが分かれば良いので、docker exec -it mysql-db bash などとして、コンテナー内にログインし、コンテナー内で mysql -uroot -pcomplexpassword すれば良いかな、と思います。実行結果の様子は後述参照。

OK、上記のように、パスワードを設定して -p と書くだけで、次の行で即座にパスワードが入力されます。結果はこんな感じ:

% mysql -uroot -pcomplexpassword -h 0.0.0.0 -P 8001
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

OK、データベースの接続を管理しました。到達してますね。エライ:smiley:

訳注
前述の通り、Windows では 0.0.0.0 へアクセスできませんので、以下のようにしてコンテナー内から MySQL を実行して確認すると良いでしょう。

> docker exec -it mysql-db bash
root@c352b4abe3ad:/# mysql -uroot -pcomplexpassword
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

訳注
唐突ですが、MySQL コマンド プロンプトに入ったついでに、下記コマンドをタイプして、データベースを作っておいてくださいませ。次章以降の演習で外側からデータベースを接続する実験になるのですが、この "Customer" データベースがないとエラーとなります。

mysql> CREATE DATABASE Customers;
Query OK, 1 row affected (0.01 sec)

mysql> 

待って、他のコンテナーからコンテナー内のデータベースに到達できるのしょうか。そこはトリッキーなところです。二つのコンテナーをリンクする必要がある個所です。

Node.js からデータベースに接続

訳注
以降の作業は、これまで作成してきたプロジェクトに追加することが想定されています。NPM パッケージのインストール等は作業してきた Node.jsプロジェクトのフォルダで行ってください。また、app.js も同じファイルを編集することが想定されています。

OK、それではデータベースに接続するコードをアプリに追加しましょう。最初に MySQL のための NPM パッケージをインストールする必要があります:

npm install mysql

次に、以下のコードを app.js の最初に追加します。

app.js
const mysql = require('mysql');

const con = mysql.createConnection({

host: "localhost",

port: 8001,

user: "root",

password: "complexpassword",

database: 'Customers'

});

con.connect(function (err) {

if (err) throw err;
 console.log("Connected!");
});

それではターミナルで試してみましょう:

% node app.js      
Example app listening on port undefined!
/Users/・・・・/node_modules/mysql/lib/protocol/Parser.js:437
      throw err; // Rethrow non-MySQL errors
      ^

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

痛みと苦悩とはこのこと:frowning:
なぜ動かないのだろう?

caching_sha2_password が MySQL 8.0 で導入されたが、Node.js ではまだ実装されていません。

OK、それがどうした、Postgres か他のデータベースで試すか?いえいえ、以下のようにコネクターに繋いで、Fix できます:

mysql -uroot -pcomplexpassword -h 0.0.0.0 -P 8001

訳注:
Windows の場合は、docker exec -it mysql-db bash してコンテナーにログイン後、mysql -uroot -pcomplexpassword してください。

MySQL のプロンプトに入ったら、次のようにタイプします。

mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'complexpassword';
mysql> FLUSH PRIVILEGES;

node app.js コマンドを再度実行しましょう。次はこうなりますよ:

% node app.js
Connected!

ついに!

訳注
この後、ポートエラーとかが出ていると思うのですが、無視していただいて結構です。これは Docker を経由せずに Node.js 単体として、app.js を呼び出しているためです。Dockerfile が設定する環境変数 "PORT" が入っていないんですね。Connected が出たかどうかが実験のすべてなので、"Connected" さえ出ていれば、エラーは気にせず進んでくださいませ。

OK、mysql_native_password の呼び出しはすべてを Fix したようですね。兎穴のより深いところに行きましょう。これって何?

MySQL はネイティブの認証を実装した mysql_native_password Plug-In を含んでいます。この認証は Plug-In 可能な認証が導入される前から使用されているパスワード ハッシュ方式です。

OK、MySQL 8 は Node.js MySQL ライブラリがまだ追いついていない新しい Plug-In 化された認証にスイッチしているということですね。これは古いバージョンの MySQL を持ってくるか、native 認証に戻せばよいということです:smiley:

訳注
先ほどの謎のコマンドで、MySQL パスワードの認証方式を caching_sha2_password から、mysql_native_password に変更しています。SHA256("シャーにごろ"とか発音しますね)はダイジェスティングの方式ですが、ここでは暗号化の方法を変えるぐらいにご理解いただければ十分かと思います。コンピューターはあらゆるところでハマりますね・・

Link 機能

Link 機能のアイディアはコンテナーは実行しているデータベースの IP や Port といった詳細を知る必要はないということに由来します。アプリ コンテナーとデータベース コンテナーがお互いに到達するといったことがちょうど例となります。典型的なシンタックスはこのようになります:

docker run -d -p 5000:5000 --name product-service --link mypostgres:postgres chrisnoring/node

少し上記をブレイクダウンしましょう:

  • アプリ コンテナー product-service と言う名前のアプリ コンテナーを作ります。
  • --link 既存の mypostgres コンテナーと product-service をリンクするコマンドを読んでいます。
  • link alias --link mypostgres:postgres は mypostgres をリンクし、 postgres と言う alias を与えています。この alias はデータベースに接続する際、product-service コンテナー内部で利用できます。

OK、 Link 機能をだいたい理解できたと思いますが、既存の my-container にどのように適合し、mysql-db データベース コンテナーにどのように link するか見ていきましょう。my-container を Link 機能なしにスタートしていますので、一旦停止・削除、--link 機能を追加パラメータで再起動する必要があります:

docker kill my-container && docker rm my-container

これで、コンテナーは終了します。起動する前に、コードをいくつか変更する必要があります。つまり、データベースに接続する部分です。--link mysql-db:mysql パラメータを使ってデータベース コンテナー と link しようとしています。これは、IP や Port 参照が不要になるという意味で、コードは次のようになります:

app.js
// part of app.js, the rest omitted for brevity

const con = mysql.createConnection({

host: "mysql",  // we changed!

user: "root",

password: "complexpassword",

database: 'Customers'

});

// and the rest of the code below

違いは、今やホストは、localhost やリンク先を数値でリンクする原因となっていた Port を 8001 と明示しません。僕らはリンクしたデータベースに与えた alias(e.g mysql)にフォーカスすることが全てです。コードの変更と他のライブラリーの追加から、僕らはイメージを次のようにリビルドする必要があります:

docker build -t chrisnoring/node .

今回は link を付けて起動しましょう:

docker run -d -p 8000:3000 --name my-container --link mysql-db:mysql chrisnoring/node

アウトプットをみてみましょう:

% docker logs my-container                                                             

> nodejs@1.0.0 start /app
> nodemon app.js

[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node app.js`
Example app listening on port 3000!
Connected!

アプリ コンテナーからのログを見る docker logs my-container でログを表示させると最後に、MySQL との接続成功を示すコールバック関数からの Connected! が出ています。

訳注
これは、console.log("Connected!"); のことを言っていますが、このように書かれたログを docker logs my-container で表示できる、ということですね。

今何時か分かる?BOOOM!(訳注:これ、何のジョークか分かる方、教えてください・・)

BOOOM

Link 機能の知識を広げる ―― 他の方法

OK、全部うまくいきました。アプリケーションをコンテナーに配置し、他のコンテナーにデータベースを配置し管理しました。しかし、僕らが見てきた Link 機能はレガシーとされていて、Link 機能に関する他のう方法を学ぶ必要があります。待って・・君が思うほど悪くない。実際、構文的に良くなるように見える。

この新しいやり方は、ネットワークを作る、またはカスタム ブリッジ ネットワークと呼ばれています。実際、僕らが作るネットワークの一つです。ポイントは、コンテナーが所属する特定のグループだということです。コンテナーは一つ以上のグループに横断して関係する、複数のネットワークに存在できます。そりゃまったくすごいことだ、構文を教えてくれないか?

最初に行うことは、アプリ コンテナーとデータベースコンテナーを所属させたいネットワークを作ることです。以下のコマンドでそのネットワークを作ることができます:

docker network create --driver bridge isolated_network

新しいネットワークができたので、追加のパラメータとして新しいネットワークと共に各コンテナーを作成する必要があります。

docker run -d -p 8000:3000 --net isolated_network --name my-container chrisnoring-node

上記で、--net シンタックスを用いて、isolated_network と呼ぶネットワークを作っています。残りのコンテナーを今まで通り、コンテナーの起動、実行です。簡単でしょう:smiley:

データベース コンテナーはどうでしょうか?

docker run -p 8000:3306 --net isolated_network --name mysql-db -e MYSQL_ROOT_PASSWORD=complexpassword -d mysql

--net isolated_network だけを加えて、データベース コンテナーを起動、実行しています。

コンテナーと他のコンテナーを明示的に Link する必要はもはやありません。特定のネットワークに配置するだけです。ネットワークのコンテナーは、お互いをどうコミュニケーションするか知っています。

ネットワークについては更に学ぶことがたくさんあります。たくさんのタイプや、コマンド ホストがあります。レガシー Link 機能との違いと言った要点は理解できたのではないかと思います。更に学ぶ場合は、こちらのリンクを参照してください。→ docs on networking

コンテナー設定上の一般的なデータベース管理

OK、この章の最初でファイルとしてデータベース構造を作成する方法と、シード データをファイルとして作成する方法、それらを MySQL プロンプトで一括して実行する方法を話しました。つまりこういうことです。そこにどのように構造とシード データを取得するかはあなた次第ですが、大まかなガイドラインや考え方を示そうと思います:

  • 構造(Structure) いくつかの点でこのファイルを実行したくなります。データベースに入れるためには、mysql クライアントを使って接続することと、ホストコンピューターから外部ファイルを参照することとできます。または、アプリのリポジトリとして配置することも、Dockerfile で ファイルを コンテナーの中にコピーして実行することもできます。他の方法は、Knex や Sequelize と言った マイグレーションをサポートするライブラリを確認し、マイグレーションを実行してデータベース構造を特定することです。少し異なるトピックですが、このことを行う他の方法があることをお知らせしたかったのです。
  • シード データ 構造と同じ方法でシード データを扱うことができます。これは構造を得た後に起きることで、一回限りです。アプリやデータベースのスタート毎に実行したい事ではなく、シードが基本的な構造データなのか、テスト目的で必要なデータなのかに応じて、手動で実行したい場合がほとんどです。e.g クライアントから MySQL に接続して、source コマンドを実行する

サマリー

OK、この文書では、MySQL の一般的な情報、テーブルと言った構造をどう取得するかの議論、初期/テスト用のシード データについて触れ、それらのスタンドアロンのファイルを使ってデータベースへの入れ方をカバーしました。

次に、なぜ、ホストにインストールするより、Docker コンテナーでデータベースを実行するべきか議論し、続いて、レガシー Link テクニックを使って二つのコンテナーがコミュニケーションする方法を見せました。MySQL 8 の不幸と、MySQL Node.js モジュールが同期していない事実に時間を費やし、それを Fix しました。

レガシー Link 機能をカバーして、それで終わりにするわけにはいかず、コンテナーをネットワーク名を使って Link する新しい方法について話す必要がありました。

最後に、データベースの管理と希望について一般的なガイドラインを共有し、現時点では、データベースをアプリにどのように追加し、アプリの開発を続けていくか理解したところにいます。

Twitter をフォローして、トピックへのあなたの問い合わせやご質問、提案を頂けるとハッピーです。

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

DockerでMySQLなどのテスト環境を作っていたら(errno: 150 "Foreign key constraint is incorrectly formed")が出た話

背景

mariadbをdocker環境に移してテストしようとしたところ、30分くらい詰まってしまったのでここに供養します。

現象

外部参照用のテーブルを新規に作成しようとすると下記のエラーが出る。

ERROR 1005 (HY000): Can't create table `{dbname}`.`{tablename}` (errno: 150 "Foreign key constraint is incorrectly formed")

原因(1)

参照しようとしている行がユニークでないためエラーになっていた。
下記のようなSQLで、重複データを削除し プレマリキーとした。

CREATE TEMPORARY TABLE {table name}_tmp AS SELECT id,MIN(uid),MIN(name) FROM tweets GROUP BY id;
DELETE FROM {table name};
INSERT INTO {table name} SELECT * FROM {table name}_tmp;
DROP TABLE {table name}_tmp;
ALTER TABLE {table name} ADD PRIMARY KEY (id);

原因(2)

参照先と参照元の型が異なる場合に発生する。
同一の方であることを確認した。

原因(3)

テーブルのcharsetが異なる場合に発生する。
下記のコマンドで確認する。

SHOW CREATE TABLE {table name};

とりあえず、対象テーブルを同一なcharsetに修正する。
※データが入っていると色々面倒ですが、私は何も入っていないのですんなり行きました。

ALTER TABLE {table name} CONVERT TO CHARACTER SET {char set};

あと、外部参照がある、テーブルにも設定させる

create table{table name}(
   {col} varchar(23) not NULL,
    ...
)ENGINE=InnoDB DEFAULT CHARSET={char set};

最後に

私は1と3で発生していました。
備忘録です、忘れぬように ここに刻む

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

Podmanでコンテナを動かす

しばらく前にアップグレードした Fedora 31 で Docker を動かそうとしたところ、エラーでコンテナを起動できない...

$ docker run node/test
docker: Error response from daemon: cgroups: cgroup mountpoint does not exist: unknown.
ERRO[0000] error waiting for container: context canceled 

Fedoraの最新版では Cgroup V1 から Cgroup V2 への移行が行われたが、Docker ではまだ Cgroup V2 をサポートしていないことが原因らしい。

https://fedoraproject.org/wiki/Changes/CGroupsV2

そもそもFedoraではDockerパッケージは提供されていない。Cgroup V1に戻すことで使うこともできるが、おすすめは podman らしい。

https://fedoraproject.org/wiki/Common_F31_bugs#Other_software_issues

The Docker package has been removed from Fedora 31. It has been replaced by the upstream package moby-engine, which includes the Docker CLI as well as the Docker Engine.
However, we recommend instead that you use Package-x-generic-16.pngpodman, which is a Cgroups v2-compatible container engine whose CLI is compatible with Docker's.

Podman

Redhatが開発したコンテナ管理パッケージ。
オープンソースで、コンテナとイメージはOCI互換、CLIはDockerと互換性がある。
コンテナの管理はsystemdに統合されているらしい。(デーモンレス)

https://podman.io/getting-started/
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/building_running_and_managing_containers/using-systemd-with-containers_building-running-and-managing-containers

インストール

docker-ceは削除

$ sudo dnf remove -y docker-ce*

podmanをインストール

$ sudo dnf install -y podman podman-compose podman-docker
  • podman コンテナの管理ツール。Docker互換のCLIを含む。
  • podman-compose docker-compose.ymlをpodmanをバックエンドにして動かすためのツール。
  • podman-docker dockerコマンドでpodmanを呼ぶシェルスクリプトを提供する。いらないけど一応入れてみた。

インストールを確認

$ podman -v
podman version 1.9.2

Podmanでコンテナイメージを起動する

Podman でも docker.io で配布されているイメージを利用することが出来る。
リポジトリの設定は /etc/containers/registries.conf にある。

registries.conf
[registries.search]
registries = ['registry.fedoraproject.org', 'registry.access.redhat.com', 'registry.centos.org', 'docker.io']

左から定義されている順にイメージの検索が行われる。既定で docker.io も利用できるようになっている。

動作確認に簡単な Dockerfile を用意した。nodeのイメージをベースにしてシェルを起動するだけのイメージ。

FROM node:lts-alpine
ENTRYPOINT /bin/sh

ビルドする。

$ podman build ./ -t node/test
STEP 1: FROM node:lts-alpine
STEP 2: ENTRYPOINT /bin/sh
STEP 3: COMMIT node/test
--> 3d522a27844
3d522a278442b3e028c8fdc3d0634d4e348ea54a403875d03734450c5f99b178

イメージの確認

$ podman image ls
REPOSITORY               TAG          IMAGE ID       CREATED          SIZE
localhost/node/test      latest       3d522a278442   13 minutes ago   93.1 MB
<none>                   <none>       7bf7394c1846   14 minutes ago   93.1 MB
docker.io/library/node   lts-alpine   7a48db49edbf   3 weeks ago      93.1 MB

コンテナの起動

$ podman run -it --rm node/test
/ # npm -v
6.14.4

podman-compose でイメージを起動する

簡単な docker-compose.yml ファイルを作成。

docker-compose.yml
version: '2'
services:
  node:
    build: .

イメージを実行する

$ podman-compose run --rm node
podman pod create --name=environment --share net
b740e843a42a7c85fe68dc1d72b27ee78e3b79c5806dfdcc0b45caea31501eeb
0
Namespace(T=False, cnt_command=[], command='run', detach=False, dry_run=False, e=None, entrypoint=None, file=['docker-compose.yml'], label=None, name=None, no_ansi=False, no_cleanup=False, no_deps=False, podman_path='podman', project_name=None, publish=None, rm=True, service='node', service_ports=False, transform_policy='1podfw', user=None, volume=None, workdir=None)
podman run --rm -i --name=environment_node_tmp1612 --pod=environment --label io.podman.compose.config-hash=123 --label io.podman.compose.project=environment --label io.podman.compose.version=0.0.1 --label com.docker.compose.container-number=1 --label com.docker.compose.service=node --add-host node:127.0.0.1 --add-host environment_node_1:127.0.0.1 --tty environment_node
/ # node -v
v12.16.3

気になったところあれこれ

  • podman-compose upでサービス毎に起動出来ない。(最新版とかではひょっとすると実装されているかも)
$ podman-compose up -d node
services ['node']
Traceback (most recent call last):
  File "/usr/bin/podman-compose", line 11, in <module>
    load_entry_point('podman-compose==0.1.6.dev0', 'console_scripts', 'podman-compose')()
  File "/usr/lib/python3.7/site-packages/podman_compose.py", line 1267, in main
    podman_compose.run()
  File "/usr/lib/python3.7/site-packages/podman_compose.py", line 755, in run
    cmd(self, args)
  File "/usr/lib/python3.7/site-packages/podman_compose.py", line 939, in wrapped
    return func(*args, **kw)
  File "/usr/lib/python3.7/site-packages/podman_compose.py", line 1038, in compose_up
    return up_specific(compose, args)
  File "/usr/lib/python3.7/site-packages/podman_compose.py", line 1033, in up_specific
    raise NotImplementedError("starting specific services is not yet implemented")
NotImplementedError: starting specific services is not yet implemented
  • podman-composeexec コマンドがない。
$ podman-compose exec node /bin/sh
usage: podman-compose [-h] [-f file] [-p PROJECT_NAME]
                      [--podman-path PODMAN_PATH] [--no-ansi] [--no-cleanup]
                      [--dry-run]
                      [-t {1pod,1podfw,hostnet,cntnet,publishall,identity}]
                      {help,version,pull,push,build,up,down,ps,run,start,stop,restart}
                      ...
podman-compose: error: argument command: invalid choice: 'exec' (choose from 'help', 'version', 'pull', 'push', 'build', 'up', 'down', 'ps', 'run', 'start', 'stop', 'restart')

他にもいろいろありそうなので、お仕事に使うにはまだ早そう。
個人で使う分には何とか出来そうなので、使ってみることにします。

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

【docker】覚えたdockerコマンドをアウトプットします。

はじめに

先程、下記の記事を投稿しました。
【Docker】CentOS7.8のdocker上にnginxを起動
その中で覚えたdockerコマンドを本記事にてアウトプットしていきたいと思います。

コマンド

バージョン確認

docker --version

【実行例】

[root@tspdocker yum.repos.d]# docker --version
Docker version 19.03.9, build 9d988398e7
[root@tspdocker yum.repos.d]#

image関連

取得済みのコンテナイメージ確認

  • docker image ls
docker image ls

【実行例】

[root@tspdocker docker]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        8 days ago          127MB
[root@tspdocker docker]#
  • docker images
docker images

【実行例】

[root@tspdocker docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        8 days ago          127MB
[root@tspdocker docker]#

レジストリからイメージの検索

docker search <イメージ名>

【実行例】

[root@tspdocker docker]# docker search centos
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
centos                             The official build of CentOS.                   6012                [OK]
ansible/centos7-ansible            Ansible on Centos7                              129                                     [OK]
consol/centos-xfce-vnc             Centos container with "headless" VNC session …   115                                     [OK]
jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos -  …   114                                     [OK]
centos/mysql-57-centos7            MySQL 5.7 SQL database server                   75
imagine10255/centos6-lnmp-php56    centos6-lnmp-php56                              58                                      [OK]
tutum/centos                       Simple CentOS docker image with SSH access      46
centos/postgresql-96-centos7       PostgreSQL is an advanced Object-Relational  …   44
kinogmt/centos-ssh                 CentOS with SSH                                 29                                      [OK]
pivotaldata/centos-gpdb-dev        CentOS image for GPDB development. Tag names …   11
guyton/centos6                     From official centos6 container with full up …   10                                      [OK]
nathonfowlie/centos-jre            Latest CentOS image with the JRE pre-install …   8                                       [OK]
drecom/centos-ruby                 centos ruby                                     6                                       [OK]
centos/tools                       Docker image that has systems administration …   6                                       [OK]
pivotaldata/centos                 Base centos, freshened up a little with a Do …   4
darksheer/centos                   Base Centos Image -- Updated hourly             3                                       [OK]
pivotaldata/centos-mingw           Using the mingw toolchain to cross-compile t …   3
pivotaldata/centos-gcc-toolchain   CentOS with a toolchain, but unaffiliated wi …   3
miko2u/centos6                     CentOS6 日本語環境                                   2                                       [OK]
blacklabelops/centos               CentOS Base Image! Built and Updates Daily!     1                                       [OK]
mcnaughton/centos-base             centos base image                               1                                       [OK]
indigo/centos-maven                Vanilla CentOS 7 with Oracle Java Developmen …   1                                       [OK]
pivotaldata/centos7-dev            CentosOS 7 image for GPDB development           0
smartentry/centos                  centos with smartentry                          0                                       [OK]
pivotaldata/centos6.8-dev          CentosOS 6.8 image for GPDB development         0
[root@tspdocker docker]#

コンテナイメージの取得

docker pull <イメージ名>

【実行例】

[root@tspdocker docker]# docker pull miko2u/centos6
Using default tag: latest
latest: Pulling from miko2u/centos6
67f15db7c18f: Pull complete
509a26fd7457: Pull complete
fc1eb556a306: Pull complete
a64d7cf12062: Pull complete
Digest: sha256:e0fde5482f052a54b8215300cbe06ec233e0527d70fe8b89e0b4a81be1b30a3c
Status: Downloaded newer image for miko2u/centos6:latest
docker.io/miko2u/centos6:latest
[root@tspdocker docker]#

コンテナイメージ削除

docker rmi <[REPOSITORY] or [IMAGE ID]>

【実行例】

①削除するコンテナの確認

[root@tspdocker docker]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        8 days ago          127MB
miko2u/centos6      latest              092ba03e36dd        3 years ago         248MB
[root@tspdocker docker]#

→今回は「miko2u/centos6」を削除

②コンテナ削除

[root@tspdocker docker]# docker rmi miko2u/centos6
Untagged: miko2u/centos6:latest
Untagged: miko2u/centos6@sha256:e0fde5482f052a54b8215300cbe06ec233e0527d70fe8b89e0b4a81be1b30a3c
Deleted: sha256:092ba03e36ddfcb49881eba3b708f461b7334cc7c595411350b04258495bd160
Deleted: sha256:c6c375cf9281546ef63130efff84f0732fc45bfaca98307eb8055b0acd4392ef
Deleted: sha256:0d222776efc8d8e95f128486c9df597c8f97148d700a585e92dd741b1d237d0c
Deleted: sha256:6128ee232c96b4419361c6855b26025ec74e66490b281f900a332f356554843e
Deleted: sha256:b1b065555b8aba5ae83d5d59d611a6b0cc470e9c14b7e4bee081398309e474a5
[root@tspdocker docker]#

③コンテナが削除されていることを確認

[root@tspdocker docker]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        8 days ago          127MB
[root@tspdocker docker]#

コンテナ起動/停止関連

起動済みコンテナ確認

docker ps
よく使うオプション 内容
-a 全てのコンテナ情報出力

【実行例】

  • docker ps
[root@tspdocker docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b631bfb26b8e        nginx               "nginx -g 'daemon of…"   4 hours ago         Up 4 hours          0.0.0.0:8080->80/tcp   vibrant_engelbart
[root@tspdocker docker]#
  • docker ps -a
[root@tspdocker docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b631bfb26b8e        nginx               "nginx -g 'daemon of…"   4 hours ago         Up 4 hours          0.0.0.0:8080->80/tcp   vibrant_engelbart
[root@tspdocker docker]#

コンテナの作成

docker run -it <イメージ名>
オプションの意味 内容
-it コンソールに結果を出力

こちらのコマンドは、コンテナの作成&起動&ログインを同時にやってくれるコマンドになります。

【実行例】

[root@tspdocker docker]# docker run -it ubuntu
root@644f6b5a46b9:/#

コンテナの起動

docker start <CONTAINER IDまたはNAME>

【実行例】

①「ubuntu」が停止されていることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              11 minutes ago      Exited (0) 13 seconds ago                          intelligent_hamilton
[root@tspdocker docker]#

→「Exited」が表示されていることを確認

②「ubuntu」を起動する

[root@tspdocker docker]# docker start 644f6b5a46b9
644f6b5a46b9
[root@tspdocker docker]#

→「644f6b5a46b9」はコンテナID

「ubuntu」が起動されていることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              12 minutes ago      Up 8 seconds                               intelligent_hamilton
[root@tspdocker docker]#

→「Up」になっていることを確認

コンテナの停止(コンテナにログインしていない場合)

docker stop <CONTAINER IDまたはNAME>

【実行例】

①「ubuntu」が起動していることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              23 minutes ago      Up 10 minutes                              intelligent_hamilton
[root@tspdocker docker]#

→「Up」になっていることを確認

②「ubuntu」を停止する

[root@tspdocker docker]# docker stop 644f6b5a46b9
644f6b5a46b9
[root@tspdocker docker]#

③「ubuntu」が停止されていることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              24 minutes ago      Exited (0) 29 seconds ago                          intelligent_hamilton
[root@tspdocker docker]#

→「Exited」になっていることを確認

コンテナの停止(コンテナにログインしている場合)

exit

【実行例】
①コンテナ「ubuntu」にログイン

[root@tspdocker docker]# docker attach 644f6b5a46b9
root@644f6b5a46b9:/#

②「exit」実行

root@644f6b5a46b9:/# exit
exit
[root@tspdocker docker]#

③「ubuntu」が停止していることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              30 minutes ago      Exited (0) 2 minutes ago                          intelligent_hamilton
[root@tspdocker docker]#

→「Exited」になっていることを確認

動作中のコンテナへログイン

  • attach
docker attach <CONTAINER IDまたはNAME>

【実行例】

①「ubuntu」が起動していることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              35 minutes ago      Up 11 seconds                              intelligent_hamilton
[root@tspdocker docker]#

②「ubuntu」のコンテナにログインできることを確認

[root@tspdocker docker]# docker attach 644f6b5a46b9
root@644f6b5a46b9:/#

※抜ける際は、「Ctrl」を押しながら「p」→「q」の順番で押す。

root@644f6b5a46b9:/# read escape sequence
[root@tspdocker docker]#
  • exec
docker exec -it <CONTAINER IDまたはNAME> /bin/bash
オプション名 内容
i 標準入力(STDIN)を開いたままにする
t 擬似ttyに接続する。ディスプレイ(STDOUT)をつなぐイメージ

【実行例】

①「ubuntu」が起動していることを確認

[root@tspdocker docker]# docker ps -a | grep ubuntu
644f6b5a46b9        ubuntu              "/bin/bash"              35 minutes ago      Up 11 seconds                              intelligent_hamilton
[root@tspdocker docker]#

②「ubuntu」のコンテナにログインできることを確認

[root@tspdocker docker]# docker exec -it 644f6b5a46b9 /bin/bash
root@644f6b5a46b9:/#

※抜ける際は、「Ctrl」を押しながら「p」→「q」の順番で押す。

root@644f6b5a46b9:/# read escape sequence
[root@tspdocker docker]#

参考

Dockerコンテナの作成、起動〜停止まで
Docker コマンドチートシート
Dockerコンテナ内で操作 attachとexecの違い
初心者用Docker基本コマンド一覧(新旧スタイル対応)

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

docker compose upしてもlocalhostに接続できないとき

Dockerでlocalhostに接続できない

Mac環境でRails開発をしているときに、Dockerを取り入れたのでdocker compose upをしたところ、正常に起動しているのにlocalhostに接続できない現象が発生。

セキュリティソフト(ESET)が影響していた

Docker自体は正常に起動しているので調べ方も特にわからず1時間くらい悩みましたが、ふとセキュリティソフトが影響しているのではと思いました。
私はMacBookにセキュリティソフト(ESET)を入れており、ファイアウォールの設定をしていたので、試しにファイアウォールの設定を切ったところ、無事localhostに接続できました。

ただ、できればファイアウォールは切りたくない、、、
他に解決方法がないか調べていたところ、CANONのサポート情報に解決方法が載っていました。

Mac環境で特定の通信が遮断される(「パーソナルファイアウォール機能」に起因する場合)

これでファイアウォールを切らず、Dockerによる通信のみ許可するように設定変更できました。

同じようにお困りの方の参考になれば幸いです。

参考

DockerとESETセキュリティソフトとの相性が悪いみたい

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

MySQLのコンテナを作る方法

  • 環境
    • CentOS Linux release 7.8.2003 (Core)
    • Docker Engine 19.03.8
    • docker-compose version 1.25.5

1. docker-compose.ymlを作る

version: '3.8'
services:
  app:
...省略...
  logdb:
    image: mysql:8.0.20
    environment:
      MYSQL_DATABASE: logdb
      MYSQL_USER: log
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
      MYSQL_TCP_PORT: 3306
    ports:
      - 3304:3306
    volumes:
      - ./logdb/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./logdb/init:/docker-entrypoint-initdb.d
    container_name: logdb
    restart: always

imageにはDockerHubにあるMySQLを指定

指定のやり方はいくつかあるようだが、後でバージョンがわかる書き方にしてみた。
mysql - Docker Hub

environmentにデータベースの情報を指定

  • MYSQL_DATABASE : 初期作成するデータベース名を指定
  • MYSQL_USERMYSQL_PASSWORD : MYSQL_DATABASEで指定したデータベースのスーパーユーザーになるユーザーとそのパスワードを指定
  • MYSQL_ROOT_PASSWORD : rootユーザーのパスワードを指定
  • MYSQL_TCP_PORT : MySQLのポート番号を指定
    • 指定しなくても3306になりそうだけれど自信がないので指定しておく

portsに公開するポートを指定

ほかのコンテナやホストの外部からデータベースを使えるように{ホストでのポート}:{コンテナでのポート}を指定

volumesの指定

設定ファイルの配置

文字コードなどの必要な設定を記載した設定ファイルmy.cnfを用意しておき/etc/mysql/conf.dに配置する

my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'
skip-character-set-client-handshake
port=3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

[mysqldump]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4

初期テーブル作成用SQLの配置

最初に作成しておいてほしいテーブル定義を書いたSQLをinitディレクトリに格納しておきdocker-entrypoint-initdb.dに配置するとデータベース作成後に作成しておいてもらえる
データを作成しておきたい場合もSQLをディレクトリに入れておけば実行してもらえる

USE logdb;

DROP TABLE IF EXISTS rhel6;
CREATE TABLE rhel6 (
-- ...省略...
);

DROP TABLE IF EXISTS rhel7;
CREATE TABLE rhel7 (
-- ...省略...
);

restartでコンテナの自動起動を設定

always(常に再起動)を設定することでホストを起動したときに自動で起動してもらえる

2. コンテナを作る

--no-recreateをつけて既存のコンテナを作り直さないようにしてコンテナを作成する

$ docker-compose up -d --no-recreate --build
...省略...
Creating logdb                   ... done

$ docker ps
CONTAINER ID       IMAGE             COMMAND            CREATED             STATUS              PORTS                             NAMES
625ce72a719        mysql:8.0.20      "docker-entry…"   23 seconds ago      Up 21 seconds       33060/tcp, 0.0.0.0:3304->3306/tcp logdb
5cead7ffb9b        host-java...      "/usr/sbin/init"   7 hours ago         Up 28 minutes       0.0.0.0:18080->8080/tcp           app

3. データベースにログインしてみる

ホストからログイン

ホストからつなぐときは、[コンテナに入る] > [データベースにログイン]でちょっと面倒くさい
けれどホストからつなぐことはあまりない・・・と思う

# 1.コンテナに入る
$ docker exec -it logdb bash

# 2. データベースにログイン
root@793f7ed80b16:/# mysql -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

# my.cnfの設定が使われてるっぽい
mysql> select default_character_set_name, default_collation_name from information_schema.schemata where schema_name = 'logdb';
+----------------------------+------------------------+
| DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+----------------------------+------------------------+
| utf8mb4                    | utf8mb4_general_ci     |
+----------------------------+------------------------+
1 row in set (0.00 sec)

# テーブルもできている
mysql> show tables;
+-----------------+
| Tables_in_logdb |
+-----------------+
| rhel6           |
| rhel7           |
+-----------------+
2 rows in set (0.00 sec)

mysql>

アプリ用コンテナからログイン

ほかのコンテナからログインするときは-h(ホスト)に「コンテナ名」を指定する

$ mysql -h logdb -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

ローカルPC(Windows)のGitBashでログイン

ホスト外部からログインするときは-h(ホスト)に「ホストのIPアドレス」を-P(ポート)に「docker-compose.ymlで指定したホストのポート」を指定する
winptyはGitBashを使用しているからつけているだけなので普通はいらない

$ winpty mysql -h {ホストのパブリックIP} -P 3304 -u log -D logdb -p
Enter password: *******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

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

WSLでdockerをinstallするときにハマった話

はじめに

基本的には、dockerの公式サイトを参考にinstallを進めます。ちなみにWSLでdockerをinstallします。

Install Docker Engine on Debian

環境

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
C:\Users\user>ver

Microsoft Windows [Version 10.0.18362.836]

(windows subsystem for linux)

➀GnuPG

$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
gpg: can't connect to the agent: IPC connect call failed

gpg、別名は「Gnu Privacy Guard」「GPG」「GnuPG」である。

これは、公開鍵でファイルの署名を検証したり、公開鍵と秘密鍵のペアでメールの暗号化・復号化を行ったり署名を添付したりするツールである。

解決方法Ⅰ

システム上でgpg-agentがすでに実行されている可能性があるので、gpg-agentを起動しなおす。

$ pkill -9 gpg-agent
$ source <(gpg-agent --daemon)

解決方法 Ⅱ

gpgをinstallし直す。自分はこれで解決した。

$ apt remove gpg
$ apt install gnupg1

➁apt-add-repository

~$ sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
Hit:1 http://archive.ubuntu.com/ubuntu focal InRelease
Get:2 http://archive.ubuntu.com/ubuntu focal-updates InRelease [107 kB]
Ign:3 https://download.docker.com/linux/debian focal InRelease
Err:4 https://download.docker.com/linux/debian focal Release
  404  Not Found [IP: 2600:9000:2157:4000:3:db06:4200:93a1 443]
Get:5 http://archive.ubuntu.com/ubuntu focal-backports InRelease [98.3 kB]
Get:6 http://security.ubuntu.com/ubuntu focal-security InRelease [107 kB]
Reading package lists... Done
E: The repository 'https://download.docker.com/linux/debian focal Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

まだ公式にfocal versionがリリースされていないようである。(2020/05/18)

解決方法

$ sudo vi /etc/apt/sources.list

focal (ubuntu20.04) stableをコメントアウトして、eoan (ubuntu19.10) stableを追記する

# deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
deb [arch=amd64] https://download.docker.com/linux/ubuntu eoan stable
# deb-src [arch=amd64] https://download.docker.com/linux/ubuntu focal stable

参考) Can’t install docker on Ubuntu 20.04

➂docker daemon

~$ sudo docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

解決方法

(以下のコマンドはwslを「管理者として実行」から開く)

$ service docker start
 * Starting Docker: docker
$ service docker status
 * Docker is running

➃ユーザの所属グループ

$ docker run hello-world
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

解決方法

$ grep -i docker /etc/group
docker:x:999:
$ sudo gpasswd -a userhoge docker
[sudo] password for userhoge:
Adding user userhoge to group docker
$ grep -i docker /etc/group
docker:x:999:userhoge
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでMySQLを起動して、Intelij IDEAで接続する方法

DockerでMySQLを起動して、Intelij IDEAにdockerプラグインを導入して接続する方法を紹介します。画像多めです。

作業環境

OS:Windows 10
エディション:HOME
バージョン:2004

事前準備

①Windowsを最新版にアップデートする

下記のサイトを参考に、Windows 10 HOMEの場合は必ず最新版までアップデートしておきます。
https://www.atmarkit.co.jp/ait/articles/1701/07/news037.html
最新版になるまで、何回もやる可能性があります。下のような画面になれば、OKです。
202005191040.png

②IntelliJ IDEAのインストールする

以下のサイトを参考にIntelliJ IDEAの Community Edition をインストールし、日本語化します。
https://sukkiri.jp/technologies/ides/intellij-idea/intellij-idea-win.html
※Editionが2つあるので、注意してください。
202005241417.png

③Dockerをインストールする

以下のサイトを参考に、Dockerをインストールします。
https://techracho.bpsinc.jp/ebi/2020_03_27/90477

Windows 10 HOMEの場合は、インストール方法が特殊なので、下記のサイトを参考にインストールしてください。
https://tech.guitarrapc.com/entry/2020/04/21/034236

④Dockerの設定

Dockerのインストールが終わったら、起動して、上の歯車のアイコンを押して、設定を開きます。
202005191315.png
「General」の中にある「Expose daemon on …」をオンにし、下にある「Apply & Restart」を押します。
※Dockerの画面が出ない場合は、ここからアクセスします。
202005190946.png

サンプルソースをダウンロードする

今回は下記のサイトから、サンプルコードをダウンロードします。
https://github.com/miyabayt/spring-boot-doma2-sample
下の画像にように、「Clone or download」という緑のボタンを押すと、下のような画面が出てくるので、「Download ZIP」を押してダウンロードします。
202005191300.png
ZIPファイルをダウンロードして、デスクトップなどに解凍してから、Cドライブ直下に移動してください。
202005200019.png
私の環境下では、Cドライブ直下に解凍すると、下記のように解凍されました。元のフォルダの構成がとは異なるので、エラーの原因になります。上記の画像と同じ構成になるように解凍してください。
202005192249.png

IntelliJ IDEAにプラグインを導入する

事前準備が完了したら、IntelliJ IDEAに4つプラグインを導入します。

①Lombok pluginをインストールする

「構成」→「プラグイン」を押します。
202005191058.png
下記のような、プラグインを追加する画面に変わります。
202005191100.png
赤枠で囲ったところに「Lombok」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191103.png

②Eclipse Code Formatterをインストールする

次に「Eclipse Code Formatter」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191218.png

③Dockerをインストールする

次に「Docker」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191223.png

④Python Community Editionをインストールする

次に「Python Community Edition」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191226.png
※このプラグインはIntelliJ IDEAからおすすめされて入れたので、不要の可能性もあります。
プラグインのインストールが終わったら、OKを押すと前の画面に戻ります。

導入したプラグインを設定する

次にプラグインの設定をしていきます。
「構成」→「設定」を押し、設定の画面を開きます。
202005191056.png

①Lombok pluginの設定

左側の「ビルド、実行、デプロイ」を押し、「コンパイラー」を開き、その中の「注釈プロセッサー」を押します。
202005191016.png
右側の画面が変わるので、「注釈処理を使用可能にする」にチェックを入れ、上の画面のようになればOKです。

②Eclipse Code Formatterの設定

左側の「その他の設定」→「Eclipse Code Formatter」を押します。
202005191020.png
右側の画面が変わるので、「Use the Eclipse code formatter」にチェックを入れ、「Eclipse Java Formatter config file」の右の「参照」を押すと、ファイル選択の画面が出てきます。
202005191021.png
先程解凍した「spring-boot-doma2-sample-master」というフォルダを開き、その中の「eclipse-formatter.xml」を選びます。

eclipse-formatter.xmlまでのパスは、Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、下記の通りになります。
C:\spring-boot-doma2-sample-master\eclipse-formatter.xml

③Dockerの設定

左側の「ビルド、実行、デプロイ」を押し、「Docker」を押します。
202005191014.png
「TCPソケット」を選び、接続が完了すればOKです。
接続できない場合は、まずはDockerが起動しているかどうか確認してください。

以上でプラグインの設定は終了です。

IntelliJ IDEAの設定を変更する

プラグインの設定が完了したら、IntelliJ IDEAの設定を変更していきます。

①bootRunを実行している場合でもビルドされるようにする

Intellij上で「Ctrl+Shift+A」を押すと、小さい画面が出てくるので、「レジストリー」と入力します。
202005191328.png
すると下に「レジストリー」と出てくるので、ここを選びます。
202005191331.png
「compiler.automake.allow.when.app.running」という項目探して、右側のチェックボックスにチェックを入れます。終わったら、「閉じる」を押します。

②コンソール出力の文字化けを防ぐ

Windowsの場合は、コンソール出力が文字化けするため、C:¥Program Files¥JetBrains¥IntelliJ Idea xx.x.x¥binの中にある「idea64.exe.vmoptions」というファイルを開きます。
202005191338.png
一番下の行に「-Dfile.encoding=UTF-8」を追記して保存します。
202005191339.png

③Java11を設定する

「構成」→「プロジェクト構造」を選びます。
202005191345.png
設定が開くので、「プロジェクト設定」→「プロジェクト」を開き、「プロジェクトSDK」と「プロジェクト言語レベル」をそれぞれ、「11」を選びます。
202005191352.png
もし、「プロジェクトSDK」で「11java version “11.0.7”」といった項目が出ない場合は、以下のページより「Java SE 11 (LTS)」の「JDK Download」からダウンロードして、インストールしてください。
https://www.oracle.com/java/technologies/javase-downloads.html

※詳しいインストール手順が必要な場合はこちらを参考にしてみてください。
https://sukkiri.jp/technologies/processors/jdk/jdk-win_install.html

DockerでMySQLを起動する

初回起動の場合

初回起動の場合は、以下の手順でMySQLを起動します。
202005191610.png

①docker-compose.ymlが存在するフォルダを確認する

サンプルコードの中には、DockerでMySQLを起動するための設定ファイル「docker-compose.yml」が含まれています。
202005200106.png
Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、「C:\spring-boot-doma2-sample-master\docker」にあります。

②Windows Power Shell を管理者権限で起動する

Dockerにコンテナなどを追加するので、タスクバーのwindowsマークの上で右クリックして、Windows Power Shell を管理者権限で起動します。
202005200041.png

③Windows Power ShellからDockerのMySQLを起動する

急にWindows Power Shellが出てきて、難しそうですが、入力するのは以下の2行だけです。

cd C:\spring-boot-doma2-sample-master\docker
docker-compose up

先程の「docker-compose.yml」というファイルが存在するフォルダまで移動します。Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、以下のようになります。

cd C:\spring-boot-doma2-sample-master\docker

“docker-compose”というコマンドが使えるかどうかを確かめるために、以下のように入力します。

docker-compose --version

以下のようにバージョンが表示されればOKです。

docker-compose version 1.25.5, build 8a1c60f6

次に以下のように入力して、MySQLを起動します

docker-compose up

エラーが出てうまく行かない場合は、docker-compose.ymlが存在するフォルダまで移動してから、上記のコードを実行しているかどうか、確認してください。
このコマンドが終了すると、Dockerの画面が下記のように変わります。
202005190953.png
簡単にDockerでMySQLを起動することができますね。

2回目以降

Dockerを起動します。Dockerの画面が出ない場合は、ここからアクセスします。
202005190946.png
白いクジラのアイコンの上で右クリックをして、「Dashboard」を選びます。
202005190948.png
Dockerの画面が出てきたら、赤枠で囲った▶部分を押します。
202005190949.png
MySQLが出てくるので、赤枠で囲ったボタンを押すと、サーバーの起動が始まります。
202005190952.png
下の画面が出てくればOKです。
202005190953.png

Dockerで起動したMySQLに、Intelij IDEAを接続する

Intelij IDEAを起動して、「オープンまたはインポート」を選びます。
202005191417.png
Cドライブ直下に解凍した「spring-boot-doma2-sample-master」を選び、OKを押します。
202005191420.png
下のような画面が出てくるので、「サービス」を選びます。
202005190959.png
画面が変わると「Docker」が出てくるので、選ぶと接続が始まります。202005191000.png
接続が完了すると、以下のような画面になります。
202005191001.png
以上で、Dockerで起動したMySQLに、Intelij IDEAで接続することができました。

サンプルコードを動かす

ここからは、サンプルコードを動かしていきます。
サンプルコードを動かす前に、プラグインの設定とJavaの設定を確認してください。
確認が終了したら、Intelij IDEAの「ターミナル」を開きます。
202005191002.png

①バージョン確認

ターミナルが起動したら、以下のように入力します。

cd C:\spring-boot-doma2-sample-master

次に、以下のようにコードを入力します。

gradle -v

以下のように、バージョンが表示されます。

------------------------------------------------------------
Gradle 6.3
------------------------------------------------------------

Build time:   2020-03-24 19:52:07 UTC
Revision:     bacd40b727b0130eeac8855ae3f9fd9a0b207c60

Kotlin:       1.3.70
Groovy:       2.5.10
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.7 (Oracle Corporation 11.0.7+8-LTS)
OS:           Windows 10 10.0 amd64

②サンプルコードを動かす

次にサンプルコードを動かします。以下のように入力します。

gradlew composeUp

プログラムが終わったら、以下のように入力します。

gradlew :sample-web-admin:bootRun

しばらく待つと、95%で止まりますが、そのままでOKです。
202005191007.png
これでアプリが起動したので、http://localhost:18081/adminにアクセスします。
screencapture-localhost-18081-admin-login-2020-05-19-10_09_21 (1).png
上のような画面が出てきたら、成功です。お疲れさまでした。

この記事は先輩エンジニアからアドバイスを受け、個人ブログから移植しました。おかしいところなどありましたら、ご指摘いただけると幸いです。

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

【Docker】CentOS7.8のdocker上にnginxを起動

はじめに

dockerの学習の一環として、下記を実施しました。

1.CentOS7.8にdockerインストール
2.nginxインストール&起動
3.htmlファイル作成&表示

今回は、こちらの流れについて解説していきたいと思います。

環境

・HyperVisor
VMware Workstation 15 Player

・仮想マシン
CPU:2
メモリ:10088MB
HDD:300GB
ネットワークアダプタ:ブリッジ
※NICは1つになります。

・OS
CentOS7.5(1804)
※「yum update」により「CentOS7.8(2003)」にアップデート

[root@tspdocker yum.repos.d]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
[root@tspdocker yum.repos.d]#

※仮想マシン設定のエビデンス(ネットワークアダプタ設定)

ネットワークアダプタ.JPG

構成図

今回の構成はこちらになります。

図.JPG

事前設定

下記について事前に設定済みになります。

  • ホスト名:tspdocker
  • IPアドレス:192.168.0.40
  • DNS:8.8.8.8,8.8.4.4
    Google Public DNSを使用しています。
  • firewalld:停止/自動起動停止
  • selinux:無効
  • NTP:設定済み(ntp.nict.jp)
  • yum update:済み

手順

docker準備

旧バージョンのdockerアンインストール

yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

公式リポジトリのインストール

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

DOCKER CE のインストール

最新版のDocker CEをインストールします。

yum install -y docker-ce docker-ce-cli containerd.io

Docker の起動/自動起動

Docker起動

systemctl start docker

Docker自動起動設定

systemctl enable docker

バージョンの確認

docker --version

実行例

[root@tspdocker yum.repos.d]# docker --version
Docker version 19.03.9, build 9d988398e7
[root@tspdocker yum.repos.d]#

docker上にnginxの準備

nginxのイメージ取得

docker pull nginx

実行例

[root@tspdocker yum.repos.d]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
afb6ec6fdc1c: Pull complete
b90c53a0b692: Pull complete
11fa52a0fdc0: Pull complete
Digest: sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@tspdocker yum.repos.d]#

イメージ確認

docker images

実行例

[root@tspdocker yum.repos.d]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              9beeba249f3e        8 days ago          127MB
[root@tspdocker yum.repos.d]#

nginx起動

docker run -d -p 8080:80 nginx

実行例

[root@tspdocker yum.repos.d]# docker run -d -p 8080:80 nginx
b631bfb26b8eb469437f55731abadc6d1e308149bf89062d0282ae11db722faa
[root@tspdocker yum.repos.d]#

nginx起動確認

docker ps -a

実行例

[root@tspdocker yum.repos.d]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b631bfb26b8e        nginx               "nginx -g 'daemon of…"   10 seconds ago      Up 9 seconds        0.0.0.0:8080->80/tcp   vibrant_engelbart
[root@tspdocker yum.repos.d]#

WEB画面確認

「http://<サーバのIPアドレス>:8080」へブラウザからアクセス
例)http://192.168.0.40:8080/

アクセスするとこちらの画面が表示される。

nginx_1.JPG

実際にhtmlファイルを作成後に表示する

コンテナへログイン

コンテナ名を調べる

docker ps -a

実行例

[root@tspdocker yum.repos.d]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
b631bfb26b8e        nginx               "nginx -g 'daemon of…"   3 hours ago         Up 3 hours          0.0.0.0:8080->80/tcp   vibrant_engelbart
[root@tspdocker yum.repos.d]#

→実行例の場合は、「vibrant_engelbart」がコンテナ名。

コンテナへログイン

docker exec -it vibrant_engelbart /bin/bash

→「vibrant_engelbart」はコンテナ名

実行例

[root@tspdocker yum.repos.d]# docker exec -it vibrant_engelbart /bin/bash
root@b631bfb26b8e:/#

OSバージョン確認

cat /etc/os-release

実行例

root@b631bfb26b8e:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@b631bfb26b8e:/#

→OSが「Ubuntu」であることを確認

vim/sudoインストール

※ファイル編集に使用するパッケージになります。

インストール可能なパッケージ一覧の更新

apt-get update

実行例

root@b631bfb26b8e:/# apt-get update
Get:1 http://deb.debian.org/debian buster InRelease [121 kB]
Get:2 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [49.3 kB]
Get:4 http://security.debian.org/debian-security buster/updates/main amd64 Packages [201 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 Packages [7905 kB]
Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [7380 B]
Fetched 8350 kB in 3s (3209 kB/s)
Reading package lists... Done
root@b631bfb26b8e:/#

vimのインストール

apt-get install vim
apt-get install sudo

htmlファイルの文字化け対策

export LANG=C.UTF-8
export LANGUAGE=en_US:
env | grep LANG

※こちらは一時的な設定になります。(ログアウトするとリセットされます。)

実行例

root@b631bfb26b8e:/usr/share/nginx/html# export LANG=C.UTF-8
root@b631bfb26b8e:/usr/share/nginx/html# export LANGUAGE=en_US:
root@b631bfb26b8e:/usr/share/nginx/html#
root@b631bfb26b8e:/usr/share/nginx/html# env | grep LANG
LANGUAGE=en_US:
LANG=C.UTF-8

html作成

htmlのデフォルトのルートディレクトリは「/usr/share/nginx/html」になります。

test用htmlファイル作成

vim /usr/share/nginx/html/test.html

記載内容

<!DOCTYPE html>
<meta http-equiv="content-type" charset="utf-8">
<html>
  <head>
    <title>主な要素</title>
  </head>
  <body>
       <h1>タイトル</h1>
       <h2>副題</h2>

       <p>
        これはパラグラフです。文節を記述するためのタグです。
        一部分だけをマーキングする場合は<span>スパン</span>を使用します。
       </p>

       <h3>
         箇条書きの例
       </h3>
         <ul>
           <li>HTMLの基本</li>
           <li>スタイルの基本</li>
           <li>スクリプトの基本</li>
         </ul

         <button>OKボタン</button>
         <button>NGボタン</button>
  </body>
</html>

作成したhtmlファイル表示

「http://<サーバのIPアドレス>:8080/test.html」へブラウザからアクセス
例)http://192.168.0.40:8080/test.html

こちらの画面が表示される。

nginx_2.JPG

参考記事

Install Docker on CentOS 7
docker上のnginxのドキュメントルート
[Docker] Docker でNginx を起動して Web ページを表示する

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

Rails6 API をGKEにデプロイして動作確認する

今回Rails6 APIをGoogle Kubernetes Engineにデプロイしたので手順のみメモ
ちょっとやり方は特殊かもしれません

構成 (一部のみ)

├── .docker
│   ├── dev
│   │   ├── .bashrc
│   │   ├── Aptfile
│   │   └── Dockerfile
│   └── prod
│        ├── .bashrc
│        ├── Aptfile
│        └── Dockerfile
│   
├── dip.yml
├── docker-compose.development.yml
└── docker-compose.production.yml

手順

rails 導入

Rails 6: Docker/docker-compose/dipでrails new力を取り戻すを参考にdipを使ってrails new します。

Dockerfileとdocker-composeの作成

構成に従ってDockerfileとdocker-compose.production.ymlを作成。
今後dev環境はdipを、production環境はdocker-compose -f docker-compose.production.ymlを使っています(今後はproduction環境をもっとシンプルなものにしたい)。

build

$ docker-compose -f docker-compose.production.yml build

ローカルでの確認

$ docker-compose -f docker-compose.production.yml up

localhostで確認

push

$ docker-compose -f docker-compose.production.yml push

GKEにデプロイ

GCPからKubernetes Engineに移動
5.1 クラスタを作成
5.2 ワークロードからデプロイを選択
5.3 既存のコンテナイメージのイメージパスから「選択」→たった今となっているイメージを選択
キャプチャ1.PNG

公開

  1. デプロイ後のボタンから公開を選択  すでに同様のimageを公開などして表示されない場合などはServicesのサービスを削除する
  2. ポート番号を指定して公開
     例えばポート番号を3000に設定している場合は既存の80→3000に変更します
    キャプチャ.PNG

  3. エンドポイントを選択かURLにエンドポイントを入力して動作を確認
    Railsの初期画面が表示されます。
     キャプチャ.PNG

以上

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

Dockerのインストールでつまずいたのでメモ

暇だったのでDockerでも構築してみるか~
と軽い気持ちでやったら初手インストールでつまずいたのでメモ

【環境】
Windows10 HOME

経緯(基本Twitterで上げたもののコピペ)

Docker Desktop Installer.exeをPCへダウンロード
https://www.docker.com/get-started

ダウンロードしたDocker Desktop Installer.exeを実行。

インストール失敗。
OSのバージョンを上げろ、と言われる

OSを最新の状態にする

再度、実行。

バージョンを上げろと言われる
(確かにDockerのエラーメッセージ内のビルド番号がPCのビルド番号より上である。。。
でもOSは最新の状態だし・・・)

解決策をググる

どうやらDocker Toolboxなるものを使ってDocker環境構築できる記事を見つける(光が見える)

Docker Toolboxでの構築法をググる

現在、Docker Toolboxはダウンロードできないという記事を見つける(希望が途絶え暗闇にぶっこまれる)

根本に立ち返る

最新の状態にしたPC以上のビルド番号を求めてくるということは自身のOSは最新に見えて、実は最新じゃない!?と仮定を建てる

調べていくとどうやらWindows Insider Programに登録すれば一般公開前の最新ビルドをインストールできるらしい

Windows Insider Programに登録

設定の「システム」から最新のバージョンがないか検索をかけてみると見事にヒット!!

アップグレードして、ビルド番号がDockerが求めているもの以上である事を確認

Docker Desktop Installerを再度実行、無事インストール完了

参考にした記事

https://po-what.com/docker-install-for-win10#i-3

補足

・Docker Toolboxについて
公式見たけど、普通にインストールできるっぽい。ただし、Docker Toolboxはレガシーであり、システム要件を満たせない古いMacやWindowsシステム向けとのこと

【補足2】
Windows Insider Programについて
Windows 10 の次のレベルアップを目指すプログラム。
参加すればいろいろ特典があるらしい
https://insider.windows.com/ja-jp/about-windows-insider-program/

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

OS再起動時にWSL2 for Docker Desktopでcannot find cgroup mount が出る

この記事では基本的なWSL導入までの流れは汲みません。

進化中のWSL

WSL2から連携可能になったDocker Desktop
これでwindows上でもlinuxサーバ開発ができるヤッター!
面倒臭いデュアルブートの設定しなくて済むし、Aviutl使いながらdockerビルドとかもできるワーイ!
Microsoft Build 2020イベントでGPUサポートの話まで出た!nvidia dockerまで使えるようになったら最高や!

しかしながら、お披露目からそんなに経って無いということもあり動作に直結する細かいバグがちらほら見られる。

個人的にメンドくさいと思ってるのがタイトルの事象。

初回起動時

WSL構築当初はそもそもマウント先を指定する必要があるのでgit hub issueに則った方法は必須となる。

cgroups: cannot find cgroup mount destination: unknown 

上記エラーがでるので下記コマンドで対処

sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

これでdockerは難なく動くようになる。

OS再起動すると認識されなくなる

問題はここからでOS再起動時にdockerも立ち上がるように設定しておりdocker自体も問題なく起動しているようだが、
docker buildなりをWSL上で使おうとすると同じエラーが出て動かない。

sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

もう一度同じコマンドを打つと(当たり前だが)ディレクトリが存在しているエラーを吐き、
マウント解除してから同じコマンドぶつけても症状は変わらず。

調べてみると、どうもOS終了前の状態を記憶しているようで再起動時に同期が取れないことが原因のようである。
(リフレッシュ前にwindows側のdockerを操作するとWSL側のdockerの状態が一致していないことが確認できる)

対処法

同期取れててないなら再起動だ。もしくはWSLとdockerを連携したときの手順を思い返そう。
docker ->「setting」にある「resource」->「WSL Integration」をUbuntuを使おうとした場合、これをonにしたはずだ。
一旦offでリスタートしてからonに戻してリスタートするエラーが回避できた。

1.png

バージョン2.3.0.2の場合

コメント 2020-05-15 122035.png

五月頭にリリースされたバージョン2.3.0.2から画面が変わりました。
「Refresh」ボタンが追加されたようですが現状機能してないみたいです。今後のアップデートで実装されるのかな?

コメント 2020-05-15 121712.png

この場合「WSL Integration」の項目を全てオフにして「apply & restart」で適用させてから、もう一度項目すべてをonにして「apply & restart」すると
無事WSL上でdockerが使えるようになります。

自分の環境だと再起動するたびに必須なのですが、他の環境だとこの限りではないのかもしれません。

参考文献

https://github.com/microsoft/WSL/issues/4189#issuecomment-518277265

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

Docker Desktop for WSL2 を使ってみる

WSLを2に更新する
WSL2にCentOSを設定する
の続き
今回はWSLでDocker Desktopを使ってみます。
一旦WSLでDockerを動かしてCentOSのコンテナ環境を作ろうと思います。
WSL上にすでにCentOSいるのにね。

準備

Docker Desktop for Windowsは Windowsネイティブの Hyper-V 仮想化とネットワークを使用していました。
そのためWindows 10 Professional が前提でした。
今回はWSL2上でDocker Desktopを実行します。

準備としてWSL2を準備しておく必要がありますが、前回まで済ませているのでそちらを参照ください。
PCのOSはWindows HomeでOKです。

インストール

Docker Desktop for Windows
こちらからインストールください。

Dockerの確認

PS C:\Users\XXX> docker version #Dockerのバージョン確認
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Built:            Wed Mar 11 01:29:16 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
PS C:\Users\XXX> wsl -l -v #wsl上にいることを確認
  NAME                   STATE           VERSION
* CentOS7                Running         2
  Legacy                 Stopped         1
  kali-linux             Stopped         1
  docker-desktop-data    Running         2
  Ubuntu                 Stopped         2
  CentOS8                Stopped         2
PS C:\Users\XXX> docker run hello-world #hollow worldの起動確認
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Dockerのインストールは無事できていそうです。
ProだったらHyper-Vは動いてないよね?WSLで動いてるよね?って確認も必要かもしれないけど、HomeのOSなのでそこはなしで!

CentOSの環境を作ってみる

WSL上にいるCentOSとは別にDockerに仮想環境を作ってみます。

PS C:\Users\XXX> docker pull centos:centos7 #CentOS7 の Docker イメージを取得
centos7: Pulling from library/centos
524b0c1e57f8: Pull complete
Digest: sha256:e9ce0b76f29f942502facd849f3e468232492b259b9d9f076f71b392293f1582
Status: Downloaded newer image for centos:centos7
PS C:\Users\XXX> docker image #Docker イメージを確認
centos              centos7             b5b4d78bc90c        2 weeks ago         203MB
hello-world         latest              bf756fb1ae65        4 months ago        13.3kB
PS C:\Users\XXX> docker run -it --name="centos7f" centos:centos7 /bin/bash #コンテナ を作成・起動
[root@6fbe3d9ddbe5 /]# pwd
/
[root@6fbe3d9ddbe5 /]# exit #コンテナから出ていく
exit
PS C:\Users\XXX> docker ps #動いているコンテナリストを取得(なにもない)
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
PS C:\Users\XXX> docker ps -a #存在するコンテナリストを取得
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
6fbe3d9ddbe5        centos:centos7      "/bin/bash"         About a minute ago   Exited (0) About a minute ago                       centos7f
5484f528bb46        hello-world         "/hello"            24 minutes ago       Exited (0) 24 minutes ago                           festive_ganguly
PS C:\Users\XXX> docker start centos7f #CentOSコンテナを再開
centos7f
PS C:\Users\XXX> docker ps #起動の確認
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES   
6fbe3d9ddbe5        centos:centos7      "/bin/bash"         2 hours ago         Up 2 hours                              centos7f
PS C:\Users\XXX> docker attach centos7f #起動したコンテナに接続

接続したコンテナでの作業

とりあえずCentOSをアップデートだけしてみます。

[root@6fbe3d9ddbe5 /]# yum update
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: ftp.yz.yamagata-u.ac.jp
 * extras: ftp.yz.yamagata-u.ac.jp
 * updates: ftp.yz.yamagata-u.ac.jp
base                                                                                                                                       | 3.
extras                                                                                                                                     | 2.
updates                                                                                                                                    | 2.
(1/4): base/7/x86_64/group_gz                                                                                                              | 15
(2/4): extras/7/x86_64/primary_db                                                                                                          | 19
(3/4): updates/7/x86_64/primary_db                                                                                                         | 1.
(4/4): base/7/x86_64/primary_db                                                                                                            | 6.
Resolving Dependencies
--> Running transaction check
---> Package bind-license.noarch 32:9.11.4-16.P2.el7_8.2 will be updated
---> Package bind-license.noarch 32:9.11.4-16.P2.el7_8.3 will be an update
---> Package binutils.x86_64 0:2.27-43.base.el7 will be updated
---> Package binutils.x86_64 0:2.27-43.base.el7_8.1 will be an update
---> Package device-mapper.x86_64 7:1.02.164-7.el7_8.1 will be updated
---> Package device-mapper.x86_64 7:1.02.164-7.el7_8.2 will be an update
---> Package device-mapper-libs.x86_64 7:1.02.164-7.el7_8.1 will be updated
---> Package device-mapper-libs.x86_64 7:1.02.164-7.el7_8.2 will be an update
---> Package systemd.x86_64 0:219-73.el7_8.5 will be updated
---> Package systemd.x86_64 0:219-73.el7_8.6 will be an update
---> Package systemd-libs.x86_64 0:219-73.el7_8.5 will be updated
---> Package systemd-libs.x86_64 0:219-73.el7_8.6 will be an update
---> Package yum-plugin-fastestmirror.noarch 0:1.1.31-53.el7 will be updated
---> Package yum-plugin-fastestmirror.noarch 0:1.1.31-54.el7_8 will be an update
---> Package yum-plugin-ovl.noarch 0:1.1.31-53.el7 will be updated
---> Package yum-plugin-ovl.noarch 0:1.1.31-54.el7_8 will be an update
---> Package yum-utils.noarch 0:1.1.31-53.el7 will be updated
---> Package yum-utils.noarch 0:1.1.31-54.el7_8 will be an update
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================================================================================== Package                                        Arch                         Version                                          Repository       
===============================================================================================================================================Updating:
 bind-license                                   noarch                       32:9.11.4-16.P2.el7_8.3                          updates          
 binutils                                       x86_64                       2.27-43.base.el7_8.1                             updates          
 device-mapper                                  x86_64                       7:1.02.164-7.el7_8.2                             updates          
 device-mapper-libs                             x86_64                       7:1.02.164-7.el7_8.2                             updates          
 systemd                                        x86_64                       219-73.el7_8.6                                   updates          
 systemd-libs                                   x86_64                       219-73.el7_8.6                                   updates          
 yum-plugin-fastestmirror                       noarch                       1.1.31-54.el7_8                                  updates          
 yum-plugin-ovl                                 noarch                       1.1.31-54.el7_8                                  updates          
 yum-utils                                      noarch                       1.1.31-54.el7_8                                  updates          

Transaction Summary
===============================================================================================================================================Upgrade  9 Packages

Total download size: 12 M
Is this ok [y/d/N]: y
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
warning: /var/cache/yum/x86_64/7/updates/packages/bind-license-9.11.4-16.P2.el7_8.3.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5
Public key for bind-license-9.11.4-16.P2.el7_8.3.noarch.rpm is not installed
(1/9): bind-license-9.11.4-16.P2.el7_8.3.noarch.rpm                                                                                        |  8
(2/9): device-mapper-libs-1.02.164-7.el7_8.2.x86_64.rpm                                                                                    | 32
(3/9): device-mapper-1.02.164-7.el7_8.2.x86_64.rpm                                                                                         | 29
(4/9): yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch.rpm                                                                                 |  3
(5/9): yum-plugin-ovl-1.1.31-54.el7_8.noarch.rpm                                                                                           |  2
(6/9): yum-utils-1.1.31-54.el7_8.noarch.rpm                                                                                                | 12
(7/9): systemd-libs-219-73.el7_8.6.x86_64.rpm                                                                                              | 41
(8/9): systemd-219-73.el7_8.6.x86_64.rpm                                                                                                   | 5.
(9/9): binutils-2.27-43.base.el7_8.1.x86_64.rpm                                                                                            | 5.
                     2/18
Failed to get D-Bus connection: Operation not permitted
  Updating   : 7:device-mapper-libs-1.02.164-7.el7_8.2.x86_64                                                                                                3/18
  Updating   : 7:device-mapper-1.02.164-7.el7_8.2.x86_64                                                                                                     4/18
  Updating   : yum-utils-1.1.31-54.el7_8.noarch                                                                                                              5/18
  Updating   : yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch                                                                                               6/18
  Updating   : 32:bind-license-9.11.4-16.P2.el7_8.3.noarch                                                                                                   7/18
  Updating   : binutils-2.27-43.base.el7_8.1.x86_64                                                                                                          8/18
install-info: No such file or directory for /usr/share/info/as.info.gz
install-info: No such file or directory for /usr/share/info/binutils.info.gz
install-info: No such file or directory for /usr/share/info/gprof.info.gz
install-info: No such file or directory for /usr/share/info/ld.info.gz
install-info: No such file or directory for /usr/share/info/standards.info.gz
  Updating   : yum-plugin-ovl-1.1.31-54.el7_8.noarch                                                                                                         9/18
  Cleanup    : yum-utils-1.1.31-53.el7.noarch                                                                                                               10/18
  Cleanup    : yum-plugin-fastestmirror-1.1.31-53.el7.noarch                                                                                                11/18
  Cleanup    : 32:bind-license-9.11.4-16.P2.el7_8.2.noarch                                                                                                  12/18
  Cleanup    : yum-plugin-ovl-1.1.31-53.el7.noarch                                                                                                          13/18
  Cleanup    : 7:device-mapper-libs-1.02.164-7.el7_8.1.x86_64                                                                                               14/18
  Cleanup    : 7:device-mapper-1.02.164-7.el7_8.1.x86_64                                                                                                    15/18
  Cleanup    : systemd-219-73.el7_8.5.x86_64                                                                                                                16/18
  Cleanup    : systemd-libs-219-73.el7_8.5.x86_64                                                                                        17/18
  Cleanup    : binutils-2.27-43.base.el7.x86_64                                                                                                                                                                                                        18/18 
  Verifying  : 7:device-mapper-1.02.164-7.el7_8.2.x86_64                                                                                                                                                                                                1/18 
  Verifying  : systemd-219-73.el7_8.6.x86_64                                                                                                                                                                                                            2/18 
  Verifying  : yum-plugin-ovl-1.1.31-54.el7_8.noarch                                                                                                                                                                                                    3/18 
  Verifying  : systemd-libs-219-73.el7_8.6.x86_64                                                                                                                                                                                                       4/18 
  Verifying  : binutils-2.27-43.base.el7_8.1.x86_64                                                                                                                                                                                                     5/18 
  Verifying  : 32:bind-license-9.11.4-16.P2.el7_8.3.noarch                                                                                                                                                                                              6/18 
  Verifying  : 7:device-mapper-libs-1.02.164-7.el7_8.2.x86_64                                                                                                                                                                                           7/18 
  Verifying  : yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch                                                                                                                                                                                          8/18 
  Verifying  : yum-utils-1.1.31-54.el7_8.noarch                                                                                                                                                                                                         9/18 
  Verifying  : systemd-219-73.el7_8.5.x86_64                                                                                                                                                                                                           10/18 
  Verifying  : yum-utils-1.1.31-53.el7.noarch                                                                                                                                                                                                          11/18 
  Verifying  : 32:bind-license-9.11.4-16.P2.el7_8.2.noarch                                                                                                                                                                                             12/18 
  Verifying  : yum-plugin-ovl-1.1.31-53.el7.noarch                                                                                                                                                                                                     13/18 
  Verifying  : binutils-2.27-43.base.el7.x86_64                                                                                                                                                                                                        14/18 
  Verifying  : 7:device-mapper-libs-1.02.164-7.el7_8.1.x86_64                                                                                                                                                                                          15/18 
  Verifying  : systemd-libs-219-73.el7_8.5.x86_64                                                                                                                                                                                                      16/18 
  Verifying  : yum-plugin-fastestmirror-1.1.31-53.el7.noarch                                                                                                                                                                                           17/18 
  Verifying  : 7:device-mapper-1.02.164-7.el7_8.1.x86_64                                                                                                                                                                                               18/18 

Updated:
  bind-license.noarch 32:9.11.4-16.P2.el7_8.3       binutils.x86_64 0:2.27-43.base.el7_8.1  device-mapper.x86_64 7:1.02.164-7.el7_8.2 device-mapper-libs.x86_64 7:1.02.164-7.el7_8.2 systemd.x86_64 0:219-73.el7_8.6 systemd-libs.x86_64 0:219-73.el7_8.6
  yum-plugin-fastestmirror.noarch 0:1.1.31-54.el7_8 yum-plugin-ovl.noarch 0:1.1.31-54.el7_8 yum-utils.noarch 0:1.1.31-54.el7_8

Complete!

無事できました。
とりあえずアップデートできたのでネットワークにもつながってるぽいしOKです!

最後に

正直、DockerもよくわかってないのにWSLにCentOS環境作ってWSLのDockerにCentOS作って・・・
自分で何がしたいのかわからないですw

いつも仮想環境作ったりするとネットワークに繋がらなかったり問題が起こりますが今回はセーフ
※前回作ったCentOS8は動いてないので7使ってます。
ちょっといろいろ復習します!!

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

https-portalで簡単https対応!

前提

【初心者向け】20分でLaravel開発環境を爆速構築するDockerハンズオンを参考に設定したdocker-compose.ymlを使って、3層アーキテクチャの構築をしました。手元には以下3つのコンテナが作成されています。

  • ウェブサーバー(web)コンテナ
  • アプリケーションサーバー(app)コンテナ
  • データベースサーバー(db)コンテナ

また、VPSサーバーにこれらのファイルをアップロードし、任意のドメインでhttpの動作を確認しています。さて、https対応をするために、https-portalを使ってLet's encryptの更新を自動化したいと考えています。

作成しているdocker-compose.ymlは以下の通りです。

docker-compose.yml
version: "3"
services:
  app:
    build:
      context: ./docker/php
      args:
        - TZ=${TZ}
    volumes:
      - ./src:/work
      - ./logs:/var/log/php
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
    working_dir: /work
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_DATABASE=${DB_NAME}
      - DB_USERNAME=${DB_USER}
      - DB_PASSWORD=${DB_PASS}
      - TZ=${TZ}
  web:
    image: nginx:1.17-alpine
    depends_on:
      - app
    ports:
      - 10080:80
    volumes:
      - ./src:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      - TZ=${TZ}
  db:
    image: mysql:8.0
    volumes:
      - db-store:/var/lib/mysql
      - ./logs:/var/log/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
      - TZ=${TZ}

volumes:
  db-store:

本記事の内容

https-portalを使用するために、docker-compose.ymldocker/nginx/default.confを修正します。

docker-compose.ymlの修正

docker-compose.ymlファイルを修正していきます。結論を述べると、https-portalコンテナを追加し、ウェブサーバー(web)コンテナのみ修正しました。

docker-compose.yml
version: "3"
services:
  app:
    build:
      context: ./docker/php
      args:
        - TZ=${TZ}
    volumes:
      - ./src:/work
      - ./logs:/var/log/php
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
    working_dir: /work
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_DATABASE=${DB_NAME}
      - DB_USERNAME=${DB_USER}
      - DB_PASSWORD=${DB_PASS}
      - TZ=${TZ}
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    restart: always
    environment:
      DOMAINS: 'test.com(yourdomain) -> http://web:8000'
      # STAGE: 'production' # Don't use production until staging works
      # FORCE_RENEW: 'true'
  web:
    image: nginx:1.17-alpine
    ports:
    - 8000:8000
    depends_on:
      - app
    volumes:
      - ./src:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      - TZ=${TZ}
  db:
    image: mysql:8.0
    volumes:
      - db-store:/var/lib/mysql
      - ./logs:/var/log/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
      - TZ=${TZ}

volumes:
  db-store:

https-portalコンテナから見ていきましょう。restartまでは公式からそのまま持ってきています。

docker-compose.yml
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    restart: always
    environment:
      DOMAINS: 'test.com(yourdomain) -> http://web:8000'
      # STAGE: 'production' # Don't use production until staging works
      # FORCE_RENEW: 'true'

DOMAINSでは、左側でどのドメインを受けるか、右側でどのコンテナに転送するかを定義できます。左側にはhttpでアクセス可能なドメインを入力しましょう。また、今回はwebサーバーに転送するので、右側はこの例の通りに入力しましょう(ただし、port番号が被らなければ8000番以外でも可能です)。

docker-compose.yml
DOMAINS: 'test.com(yourdomain) -> http://web:8000'

また、本番環境の場合、STAGEのコメントを外しておきましょう。''内にはlocal or staging or productionを入れることができますが、localはLet's encryptが取得できません。

docker-compose.yml
# STAGE: 'production' # Don't use production until staging works

ウェブサーバー(web)コンテナでは、https-portalコンテナからの転送を受け取るためにポート番号を8000に変更しています。すでに述べたとおり、8000番以外を設定した場合は、その番号を設定します。

docker-compose.yml
  web:
    image: nginx:1.17-alpine
    ports:
      - 8000:8000
    depends_on:
      - app
    volumes:
      - ./src:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      - TZ=${TZ}

これでdocker-compose.ymlの修正は完了です。

docker/nginx/default.confの修正

default.confファイルを修正します。それぞれ環境が異なる可能性もありますので、どのファイルを修正するかはwebコンテナのvolumesを確認しましょう。

docker-compose.yml
   volumes:
      - ./src:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf

それではdocker/nginx/default.confを編集します。以下が設定されているので、8000番に変更しましょう(番号はDOMAINSで変更したもの)。

default.conf
server {
    listern 80
...
default.conf
server {
    listern 8000
...

最後にdockerを再起動して数分待ち、httpsでページが表示されることを確認しましょう。

$ docker-compose down
$ docker-compose up -d

お疲れさまでした!

参考

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

(備忘録)TensorFlowを使ってオススメの楽曲名を類推するWebアプリ【機械学習】

はじめに

本記事は(備忘録)TensorFlowを使ってオススメの楽曲名を類推するWebアプリ
【docker-composeで実行環境作り】
の続きです。
前回は、docker-composeでTensorFlowとFlask環境作ったので、
今回は、TensorFlow + Kerasを使った機械学習について整理したいと思います。
自分用に作った記事なので、分かりにくい点や情報、技術が古いかもしれませんがご了承ください:bow:
また何かしらのWebアプリを独りで作りたい方のご参考になれば嬉しいです。

Webアプリ実物は以下のGIFのようになります。
ezgif.com-crop.gif
検索ボックスに文章で入力すると、ハンバード・ハンバードさんの「同じ話」と言う回答頂きました:clap:
$\tiny{※学習データが少ないため、一部の曲しかヒットしません。。しょぼいです}$:bow_tone1:
$\tiny{※楽譜リンクをクリックすると楽譜の一部が表示されていますが、記事の対象外です}$:no_good_tone1:

参考文献

この記事を作るにあたって参考にさせて頂きました:bow_tone1:

TODO マップ

(備忘録)TensorFlowを使ってオススメの楽曲名を類推するWebアプリ
【docker-composeで実行環境作り】
の続きで、
今回は機械学習です。

区分 状況 内容 言語、FW、環境等
序 章 共通 アプリの概要 Python
TensorFlow
Keras
Google Colaboratory
第一章 Web API 環境構築(実行環境) docker-compose
Flask
Nginx
gunicorn
第二章 Web API (今回)機械学習 Python
TensorFlow
Keras
Flask
第三章 画面 未着手 環境構築 Python
Django
Nginx
gunicorn
PostgreSQL
virtualenv
第四章 画面 未着手 表示、Web API呼出し部分 Python
Django
第五章 AWS 未着手 AWS自動デプロイ Github
EC2
CodeDeploy
CodePipeline

※まだ記事は全然整理できていないので時間ある時につくります。
未着手のまま命尽きるかも:angel_tone2:
またマップは書いてるうちに変わる可能性ありますのでご了承下さい。。

環境

※以下のVerでなくても動くと思いますが、古いのでご注意下さい:no_good_tone2:

OS:Ubuntu 18.04.4 LTS
---------------------- -----------
Flask                  1.1.0
gunicorn               19.9.0
Keras                  2.3.1
Keras-Applications     1.0.8
Keras-Preprocessing    1.1.2
matplotlib             3.1.1
mecab-python3          0.996.2
numpy                  1.16.4
pandas                 0.24.2
Pillow                 7.1.2
pip                    20.1
Python                 3.6.9
requests               2.22.0
scikit-learn           0.21.2
sklearn                0.0
tensorflow             2.2.0

オススメ曲を類推する部分のフロー

まず、ここで作りたいは以下のような機能です。
入力して文章(曲雰囲気等)を与えるとオススメの曲名を返してくれるWeb APIです。
Web APIの実物は以下です。
Peek 2020-05-16 14-30.gif

例ではGETメソッドのパラメータとして「切なくて誰かの幸せ願う歌」とし、
JSONで「雲がゆくのは」という曲名が取得できました。
(例)Web APIリンク

このWeb API内部の処理フローは以下となっています。
image.png
フローのように最後に曲名を返しますが、途中で重みデータを読み込みます。
これは、事前に機械学習によって作成された学習済みモデルの事です。
なので、学習済みモデルを作成する方法について整理します。

機械学習のフロー

以下フローは開発者目線で、機械学習を行うまでの流れとなります。
image.png
まず、学習元のデータを準備します。こちらは人間が見ても分かるようなテキストで作ります。
次に機械(コンピュータ)に分かってもらうために前処理をします。
今回の例では、TF-IDFと呼ばれる方法で学習元のデータを数値ベクトルに変換します。
最後にMLP(多層パーセプトロン)で機械学習を行います。
各々の詳細は後述します。

学習元データの作成

学習元となるデータは以下のようにカンマ区切り作っています。
機械学習の元データ
image.png
類推対象の曲名に対して曲の情報(雰囲気、アーティスト名等)が入っています。
"|"(パイプ)で区切ってますが、無くても大丈夫です。

前処理(TF-IDF)

TF-IDFで数値ベクトルに変換します。
まず、上記で作成した学習元データを読み込みます。
その後、TF-IDF計算するために文章を単語に分けます(分かち書き)
この処理では形態素解析にMeCabを使っています。
参考までに分かち書きのソースは以下です。

以下は、Google Colaboratoryに貼り付けるコードです。
$\tiny{※凝視したらダメです}$:no_good_tone1:
上から順番に貼り付けて実行してください。。

必要なライブラリをインストール
# 必要なライブラリをインストール
!apt-get install mecab libmecab-dev mecab-ipadic-utf8
!pip3 install mecab-python3
分かち書き部分(一部抜粋)
import MeCab

# MeCabの初期化
tagger = MeCab.Tagger()

def tokenize(text):
    '''MeCabで形態素解析を行う''' 
    result = []
    word_s = tagger.parse(text)
    for n in word_s.split("\n"):
        if n == 'EOS' or n == '': continue
        p = n.split("\t")[1].split(",")
        h, h2, org = (p[0], p[1], p[6])
        if not (h in ['名詞', '動詞', '形容詞']): continue
        if h == '名詞' and h2 == '数': continue
        result.append(org)
    return result

# モジュールのテスト
if __name__ == '__main__':
    print(tokenize("映画|武田鉄矢|切ない|知らない誰かの幸せ願う"))

実行すると以下のようにコンソールに表示されると思います。

['映画', '*', '武田', '鉄矢', '*', '切ない', '*', '知る', '誰か', '幸せ', '願う']

単語ごとに区切られました。上記例は1文だけですが、
実際のプログラムではこの処理をファイル中の文章(行数)分繰り返しています。

分かち書きできたら、TF-IDFの計算します。
TF-IDFについては、わかり易い説明がありましたので引用させて頂きます。
引用元:TF-IDF

文書の中から、その文書の特徴語を抽出する時に使う値です。
いくつかの文書があったときに、それらに出てくる単語とその頻度(Frequency)から、
ある文書にとって重要な単語はなんなのかというのを数値化します

TF-IDFは以下の式で表されます。

\textrm{TF_IDF}(t) = \textrm{tf}(t,d) × \textrm{idf}(t)

また、$\textrm{tf}(t,d)$と$\textrm{idf}(t)$は以下の式で表されます。

\textrm{tf}(t,d) = \frac{n_{t,d}}{\sum_{s \in d}n_{s,d}} \textrm{  , } \textrm{idf}(t) = \log{\frac{N}{df(t)}} + 1

$n_{t,d}$ : ある単語 $t$ の文書 $d$ 内での出現回数
$\sum_{s \in d}n_{s,d}$ : 文書 $d$ 内のすべての単語の出現回数の和
$N$ : 全文書数
$df(t)$ : ある単語 $t$ が出現する文書の数

上記の式をプログラムに直すと以下になります。

TF-IDFの計算(一部抜粋)
def calc_files():
    '''追加したファイルを計算'''
    global dt_dic
    result = []
    doc_count = len(files)
    dt_dic = {}
    # 単語の出現頻度を数える
    for words in files:
        used_word = {}
        data = np.zeros(word_dic['_id'])
        for id in words:
            data[id] += 1
            used_word[id] = 1
        # 単語tが使われていればdt_dicを加算
        for id in used_word:
            if not(id in dt_dic): dt_dic[id] = 0
            dt_dic[id] += 1
        # 出現回数を割合に直す --- (*10)
        data = data / len(words) 
        result.append(data)
    # TF-IDFを計算
    for i, doc in enumerate(result):
        for id, v in enumerate(doc):
            idf = np.log(doc_count / dt_dic[id]) + 1
            doc[id] = min([doc[id] * idf, 1.0])
        result[i] = doc
    return result

※こちらの文献のサンプルソース1をほぼ流用させて頂いていますが、Githubに今回のソースをあげております。
(ソース)
学習元ファイル読み込みからTF-IDFを計算・出力するソースは以下です。
肝心のTF-IDFを計算するソースは長いのでモジュール化して読み込みます:sweat:
また、学習元のデータも読み込みます。
以下に格納していますので、アップロードしてください。
tfidfWithIni.py ← TF-IDFを計算するモジュール
ans_studyInput_fork.txt ← 学習元ファイル

TF-IDFベクトル作成手順

以下は、ご参考までにGoogle Colaboratoryに貼り付けるコードです。
$\tiny{※凝視したらダメです}$:no_good_tone1:
上から順番に貼り付けて実行してください。。

手順1_ファイルをアップロード
# ファイルをアップロード(「tfidfWithIni.py」、「ans_studyInput_fork.txt」)
from google.colab import files
uploaded = files.upload()
手順2_必要なライブラリをインストール
# ファイル保存用のディレクトリ作成
!mkdir text
# 必要なライブラリをインストール
!apt-get install mecab libmecab-dev mecab-ipadic-utf8
!pip3 install mecab-python3
手順3_TF-IDFベクトルに変換
import os, csv, glob, pickle
import tfidfWithIni
import importlib

# モジュール(tfidfWithIni)のリロード
importlib.reload(tfidfWithIni)

# 変数の初期化
y = []
x = []

# ラベルのコード変換用 辞書
labelToCode = {}

# csvファイルを読み込む
def read_file(path):
    '''テキストファイルを学習用に追加する''' # --- (*6)
    with open(path, "r", encoding="utf-8") as f:
        reader = csv.reader(f)   
        label_id = 0  
        for row in reader:
            # ラベルコード作成
            if row[2] not in labelToCode:
                labelToCode[row[2]] = label_id
                label_id += 1

            y.append(labelToCode[row[2]])  # ラベルをセット
            tfidfWithIni.add_text(row[3])  # 文章をセット
           # print("ラベル: ", row[2], "(", labelToCode[row[2]], ")",  " 文章: ", row[3])

# モジュールのテスト --- (*15)
if __name__ == '__main__':
    # TF-IDFベクトルを初期化(filesを空にする)
    tfidfWithIni.iniForOri()

    # ファイル一覧を読む --- (*2)
    read_file("ans_studyInput_fork.txt")

    # TF-IDFベクトルに変換 --- (*3)
    x = tfidfWithIni.calc_files()

    # 保存 --- (*4)
    pickle.dump([y, x], open('text/genre.pickle', 'wb'))
    tfidfWithIni.save_dic('text/genre-tdidf.dic')
    pickle.dump(labelToCode, open('text/label_to_code.pickle', 'wb'))

実行すると以下のようにフォルダーとファイルが出来上がります。
image.png

  • /content/text/genre.pickle : 単語をTF-IDFでベクトル化したもの
  • /content/text/label_to_code.pickle : 学習元ファイルを元に曲名をラベル化した辞書
  • /content/text/genre-tdidf.dic : TF-IDF計算用の辞書

TF-IDF計算用の辞書は以下のように計算に使った単語をIDに変換したものです。
image.png

機械学習(MLP)

前処理をしたので、機械学習の準備終わりました。
上記までの学習データを元に曲名を正しく判別できるように学習を行います。
学習の手法としてMLP(多層パーセプトロン)を使います。
MLPとは、人の神経を模したニューラルネットワークの一種で、
3つ以上のノードの層からなるものだそうです。
MLPはある手法で学習データ(正解となるデータ)を元に学習を行い、
未知のデータ(この例では曲の雰囲気)がきても正しく判別(この例では曲名)できるようになります。
これを行うために機械学習フレームワークのTensorFlow+Kerasを使います。
そして、今回は以下のような構造のニューラルネットワークを作ります※イメージです:sweat:
image.png

このニューラルネットワーク作るためにTensorFlow+Kerasでモデル化するとこのようになります1

# MLPモデル構造を定義
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(nb_classes, activation='softmax'))

レイヤーにはKerasのDenseと呼ばれるものを使います。これを使うと各々のパーセプトロンが次のレイヤーの
パーセプトロンに全て繋がるそうです。
また、イメージ図のx1〜xtまでが入力数ですが、これは引数のinput_shapeで定義しており、
全文章を分かち書きしてできた単語の数分です。サンプルの学習ファイルでは144個(次元)になります。
出力はy1〜yclassで学習ファイルの曲名数分あり、引数のnb_classesで指定してます。
サンプルでは10個(曲)です。

次に正しく判別できるようにどのように学習を行うか設定します(コンパイル)。
Keras Documentationのマルチクラス分類問題を元に最適化アルゴリズムとしてRMSprop、
損失関数としてcategorical_crossentropyとします。
※(言葉のイメージ)損失関数:学習のズレを計る指標、最適化アルゴリズム:正解に近づける修正方法

# モデルをコンパイル
model.compile(
    loss='categorical_crossentropy',
    optimizer=RMSprop(),
    metrics=['accuracy'])

最後に学習の実行部分です。
学習はfitメソッドで実行します。入力(曲の雰囲気等)と出力(曲名)
のNumpy配列をsequenceモデルのfitメソッドに与えると学習してくれます。

hist = model.fit(x_train, y_train,
          batch_size=16, # 1回に計算するデータ数
          epochs=150,    # 学習の繰り返し回数みたいなもの
          verbose=1,
          validation_data=(x_test, y_test))

機械学習の実行

以下は、ご参考までにGoogle Colaboratoryに貼り付けるコードです。

上記TF-IDFベクトル作成手順の手順3まで実行した上で、
以下を実行すると機械学習実行できるはずです。

手順4_機械学習(MLP)の実行
import pickle
from sklearn.model_selection import train_test_split
import sklearn.metrics as metrics
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
import matplotlib.pyplot as plt
import numpy as np
import h5py

# 分類するラベルの数
labelToCode = pickle.load(open("text/label_to_code.pickle", "rb"))
nb_classes = len(labelToCode) 

# データベースの読込
data = pickle.load(open("text/genre.pickle", "rb"))
y = data[0] # ラベルコード
x = data[1] # TF-IDF
# ラベルデータをone-hotベクトルに直す
y = keras.utils.np_utils.to_categorical(y, nb_classes)
in_size = x[0].shape[0] # 入力x[0]の要素数

# 学習用とテスト用を分ける
x_train, x_test, y_train, y_test = train_test_split(
        np.array(x), np.array(y), test_size=0.2)

# MLPモデル構造を定義
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(nb_classes, activation='softmax'))

# モデルをコンパイル
model.compile(
    loss='categorical_crossentropy',
    optimizer=RMSprop(),
    metrics=['accuracy'])

# 学習を実行
hist = model.fit(x_train, y_train,
          batch_size=16, # 1回に計算するデータ数
          epochs=150,    # 学習の繰り返し回数みたいなもの
          verbose=1,
          validation_data=(x_test, y_test))

# 評価する
score = model.evaluate(x_test, y_test, verbose=1)
print("正解率=", score[1], 'loss=', score[0])

# 重みデータを保存
model.save_weights('./text/genre-model.hdf5')

# 学習の様子をグラフへ描画
plt.plot(hist.history['val_accuracy'])
plt.title('Accuracy')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

実行終わると、以下のようなグラフが表示され、ファイル(/content/text/genre-model.hdf5)が
追加で作成されているはずです。これで機械学習終わりです。
image.png

学習済みモデルを使って曲名を類推

類推部分でも機械学習時と同様のモデルを定義します。
学習済みモデル、TF-IDF辞書、結果ラベル用辞書を読み込みます。
そして未知の文書(曲の雰囲気)をTF-IDFベクトルに変換します。
最後にSequencialが持つpredictメソッドにTF-IDFベクトル与えると曲名を類推します。

以下は、ご参考までにGoogle Colaboratoryに貼り付けるコードです。

上記 機械学習の実行の手順4まで実行した上で、
以下を実行すると曲名が類推できるはずです。

曲名の類推
import pickle, tfidfWithIni
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
from keras.models import model_from_json
import importlib

# モジュール(tfidfWithIni)のリロード
importlib.reload(tfidfWithIni)

def inverse_dict(d):
    return {v:k for k,v in d.items()}

# テキストを指定して判定
def getMusicName(text):
    # TF-IDFのベクトルに変換 
    data = tfidfWithIni.calc_text(text)
    # MLPで予測
    pre = model.predict(np.array([data]))[0]
    n = pre.argmax()
    print("オススメの楽曲名 : " + label_dic[n], "(", pre[n], ")")


# ラベルの定義
labelToCode = pickle.load(open("text/label_to_code.pickle", "rb"))
nb_classes = len(labelToCode) 
label_dic = inverse_dict(labelToCode)

# 辞書から入力 要素数を求める。
in_size_hantei = pickle.load(open("text/genre-tdidf.dic", "rb"))[0]['_id']

# TF-IDFの辞書を読み込む
tfidfWithIni.load_dic("text/genre-tdidf.dic")

# Kerasのモデルを定義して重みデータを読み込む
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size_hantei,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(nb_classes, activation='softmax'))
model.compile(
    loss='categorical_crossentropy',
    optimizer=RMSprop(),
    metrics=['accuracy'])
model.load_weights('./text/genre-model.hdf5')

if __name__ == '__main__':
    requestParam = """
    切なくて誰かの幸せ願う歌
    """
    getMusicName(requestParam)

学習結果によって変わるかもしれませんが、以下のように表示されると思います。

オススメの楽曲名 : 雲がゆくのは ( 0.99969995 )

Flaskを使ったWeb APIでの曲名類推は前回ちょっとやってますので、割愛したいと思います:sweat:

今後について

今回は機械学習まで少し整理できました。
また、時間のある時に少しづつブラッシュアップ、整理できればと思います:sob:
未定ですが、次回は画面側の環境構築について整理できればと思います。

区分 状況 内容 言語、FW、環境等
序 章 共通 アプリの概要 Python
TensorFlow
Keras
Google Colaboratory
第一章 Web API 環境構築(実行環境) docker-compose
Flask
Nginx
gunicorn
第二章 Web API 機械学習 Python
TensorFlow
Keras
Flask
第三章 画面 未着手 (次回)環境構築 Python
Django
Nginx
gunicorn
PostgreSQL
virtualenv
第四章 画面 未着手 表示、Web API呼出し部分 Python
Django
第五章 AWS 未着手 AWS自動デプロイ Github
EC2
CodeDeploy
CodePipeline
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む