20200104のdockerに関する記事は17件です。

Windows10で快適な開発環境を得るための道のり~Docker編~

作成する環境

  • Windows Subsystem for Linux(WSL)で,Docker環境を作成する.

環境

  • Windows 10 Home
    • バージョン:1903

作業ログ

WSLを有効にする

以下を参考にWSL環境を構築する.

https://www.atmarkit.co.jp/ait/articles/1608/08/news039.html

Ubuntuを導入する

Microsoft StoreからUbuntuをインストールします.(Ubuntu 18.04 LTS)

※2020/01/02現在では最新のLTS
01.png

インストール作業終了後,Ubuntuを管理者権限で起動します.

各種初期設定

とりあえずここまでで,Ubuntu環境が作成できました.

※以下は,自分が初期セットアップに実施したこと.

リポジトリの変更

データの取得先を海外のサーバから日本のサーバへと変更する.

$ sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list
パッケージのアップデート
$ sudo apt update
$ sudo apt upgrade

Docker環境構築

※WSL上でDockerの動作が確認されているのは,17.xまでとなります.

18.xはまだサポートされていないと思われます.

docker 17.12.1のインストール
$ sudo apt install docker.io=17.12.1-0ubuntu1
$ sudo cgroupfs-mount
# 現在のユーザでdockerコマンドをsudoせずに実行できるようにする.
$ sudo usermod -aG docker $USER
Dockerデーモンの起動
$ sudo service docker start
起動時に自動的にDockerデーモンが起動されるようにする
$ sudo systemctl enable docker
apt upgrade時にdockerのバージョンを変更させないようにする

※他のパッケージアップデート時につられてDockerのバージョンが上がり動作しなくなるのを防ぐためです.

$ sudo apt-mark hold docker.io
docker.io set on hold.

確認

$ apt-mark showhold
docker.io

→ OK!

バージョン確認
$ docker --version
Docker version 17.12.1-ce, build 7390fc6
Hello World

以下がコンソールに表示されればDockerのセットアップは完了です.

$ docker run --rm hello-world

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-composeをインストール

最新のバージョンを確認

こちら から最新のバージョンを確認する.

※2020/01/02現在では1.25.0が最新のバージョンです.

ダウンロード

/usr/local/bin配下にダウンロード

$ sudo curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
実行権限の付与
$ sudo chmod 0755 /usr/local/bin/docker-compose
確認
$ docker-compose --version
docker-compose version 1.25.0, build 0a186604
適当なサービスを起動してみる
$ mkdir -p docker/docker-services
$ cd docker/docker-services
$ vi docker-compose.yml
version: '3'
volumes:
  db_data:
services:
  database:
    image: postgres:11.6
    container_name: postgres
    ports:
      - 5432:5432
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"

起動時に以下のエラーが発生

$ docker-compose up
Creating network "postgres_default" with the default driver
ERROR: Failed to Setup IP tables: Unable to enable NAT rule:  (iptables failed: iptables --wait -t nat -I POSTROUTING -s 172.18.0.0/16 ! -o br-1fdb62035eeb -j MASQUERADE: iptables: Invalid argument. Run `dmesg' for more information.
 (exit status 1))

WSLのネットワーク周りの対応が完全でないことが原因とのこと.

WSL2であれば解決するらしいので,WSL → WSL2へと切り替えを行う.

WSL2への切り替え

と,いうことでWSL2でdocker-composeを使えるようにするまでを参考に作業を進める.

手順は,

  1. Windows 10 Insider Preview の登録
  2. Windows 10 Preview Build のインストール
    • 設定 > 更新とセキュリティ > Windows Insider Program
    • Windows Updateを実行する(結構時間がかかります.) ※Build Versionが18917以降の場合は必要なし
  3. WSL 2のインストール
  4. WSL 1でUbuntuのインストール(実施済みのため省略)
  5. WSL 1 -> WSL 2への切り替え
  6. dockerのインストール(実施済みのため省略)
  7. docker-composeのインストール(実施済みのため省略)

とのこと.(1, 2は省略します.)

3. WSL2のインストール

Power Shellを管理者権限で起動後,以下のコマンドを発行.(実行後再起動が必要)

PS C:\WINDOWS\system32> Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

再起動後,上記コマンドを再実行し以下の状態となればOK

PS C:\WINDOWS\system32> Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform                         

Path          :
Online        : True
RestartNeeded : False
5. WSL1 -> WSL2へ切り替え

現在のバージョンを確認

PS C:\WINDOWS\system32> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-18.04    Stopped         1

バージョンの切り替え

PS C:\WINDOWS\system32> wsl --set-version Ubuntu-18.04 2
変換中です。この処理には数分かかることがあります...
WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください
変換が完了しました。

6, 7については前工程にて実施済みのため省略します.

(今度こそ...)動作確認
$ docker-compose up
Creating network "postgres_default" with the default driver
Creating volume "postgres_db_data" with default driver
Pulling database (postgres:11.6)...
11.6: Pulling from library/postgres
804555ee0376: Pull complete
dc6ae8802d84: Pull complete
395ccdd34b05: Pull complete
a97aec38ba66: Pull complete
38ca37422b05: Pull complete
4f48902af5dd: Pull complete
f3aa2278d16c: Pull complete
babec8f73680: Pull complete
1b9e5f5edfb8: Pull complete
d72f7887945f: Pull complete
f16aa76dd9d7: Pull complete
71fe97949a0b: Pull complete
b8f647bf25fd: Pull complete
6598592ebb18: Pull complete
Digest: sha256:3695eeddceb287a15540881344b846c07c53518010d842e2ab0103f041a2412e
Status: Downloaded newer image for postgres:11.6
Creating postgres ... done
Attaching to postgres
postgres    | The files belonging to this database system will be owned by user "postgres".
postgres    | This user must also own the server process.
postgres    |
postgres    | The database cluster will be initialized with locale "en_US.utf8".
postgres    | The default text search configuration will be set to "english".
postgres    |
postgres    | Data page checksums are disabled.
postgres    |
postgres    | fixing permissions on existing directory /var/lib/postgresql/data ... ok
postgres    | creating subdirectories ... ok
postgres    | selecting default max_connections ... 100
postgres    | selecting default shared_buffers ... 128MB
postgres    | selecting default timezone ... Etc/UTC
postgres    | selecting dynamic shared memory implementation ... posix
postgres    | creating configuration files ... ok
postgres    | running bootstrap script ... ok
postgres    | performing post-bootstrap initialization ... ok
postgres    | syncing data to disk ... ok
postgres    |
postgres    | Success. You can now start the database server using:
postgres    |
postgres    |     pg_ctl -D /var/lib/postgresql/data -l logfile start
postgres    |
postgres    |
postgres    | WARNING: enabling "trust" authentication for local connections
postgres    | You can change this by editing pg_hba.conf or using the option -A, or
postgres    | --auth-local and --auth-host, the next time you run initdb.
postgres    | waiting for server to start....2020-01-04 14:01:29.863 UTC [48] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres    | 2020-01-04 14:01:29.891 UTC [49] LOG:  database system was shut down at 2020-01-04 14:01:29 UTC
postgres    | 2020-01-04 14:01:29.899 UTC [48] LOG:  database system is ready to accept connections
postgres    |  done
postgres    | server started
postgres    |
postgres    | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
postgres    |
postgres    | waiting for server to shut down...2020-01-04 14:01:29.947 UTC [48] LOG:  received fast shutdown request
postgres    | .2020-01-04 14:01:29.952 UTC [48] LOG:  aborting any active transactions
postgres    | 2020-01-04 14:01:29.954 UTC [48] LOG:  background worker "logical replication launcher" (PID 55) exited with exit code 1
postgres    | 2020-01-04 14:01:29.954 UTC [50] LOG:  shutting down
postgres    | 2020-01-04 14:01:29.989 UTC [48] LOG:  database system is shut down
postgres    |  done
postgres    | server stopped
postgres    |
postgres    | PostgreSQL init process complete; ready for start up.
postgres    |
postgres    | 2020-01-04 14:01:30.062 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres    | 2020-01-04 14:01:30.062 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres    | 2020-01-04 14:01:30.070 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres    | 2020-01-04 14:01:30.092 UTC [57] LOG:  database system was shut down at 2020-01-04 14:01:29 UTC
postgres    | 2020-01-04 14:01:30.100 UTC [1] LOG:  database system is ready to accept connections

→ OK!

一応確認

$ docker exec -it postgres bash
root@a48d26e23174:/# psql -U postgres postgres
psql (11.6 (Debian 11.6-1.pgdg90+1))
Type "help" for help.

postgres=#

→ OK!

まとめ

Dockerの環境を作成するだけだったのですが,そこそこ時間がかかってしまいました.(正月にのんびりのんびり作業して3日くらい)

次回

VSCodeとの連携周りを書く予定です.

参考

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

プログラミングをかじったからには何らかの制作物を作りたい#3 ~作り直し編、完成したもの~

説明

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

前回のあらすじ

プログラミングをかじったからには何らかの制作物を作りたい# 2
https://qiita.com/tatsuki1112/items/bf363ff7e0a1678eebd6
じゃんけん自体を書いたり、Bootstrapでページを一応レスポンシブ化した。

作り直しとは

じつはこのじゃんけんサイトは最初PythonのFlaskで作成していた。しかしなんとなくやる気が起きずにだいぶ放置していた。その後、PHP、Laravelを使用している会社でインターンを行うこととなったので、勉強をかねてLaravelで作成しようと思い立ち作り直して再開した。

できたもの

このエントリーを行ったときにはこのじゃんけんサイトもうすでに完成していて、やったことの整理という意味で記述しています。
一応の成果物はこちらにあるので、お暇な際にでも遊んでいただけると幸いです。
https://www.mend0.top

実際に使ったもの

Docker 19.03.5
Docker-compose 1.25.0
PHP 7.3.13
Laravel 6.3.0
nginx 1.17
mysql 8.0
jquery
Bootstrap 4

conoha vps 最安プラン
centos 7.7

こんな感じでしょうか

大いに参考にさせていただいたもの

いきなりDockerやLaravelの環境を構築するのは非常に困難なので、以下を参考に環境を整えました。

Laravelの開発環境をDockerを使って構築する
https://qiita.com/ucan-lab/items/17c806973e69792ada99

Laravel 6.0 基本のタスクリスト
https://qiita.com/ucan-lab/items/36f6e89abad26a68f69a

というかほとんどこちらのタスクリストを改変して作成したようなものです。偉大ですね。

あそびかた

それぞれの制作や公開の過程でどのような手順を踏んだかはともかくとして、とりあえずはどんな物ができたのかを御覧いただきたいと思います。

トップページ

スクリーンショット 2020-01-04 23.21.27.png

強い手を探す

指定した回数じゃんけんを行い、そのなかで最も勝数が多かった手を表示するものです。じゃんけんの手を決める自信がないときに利用してください。
スクリーンショット 2020-01-04 23.26.58.png

たとえば99999回じゃんけんを行わせると...
スクリーンショット 2020-01-04 23.28.17.png

このように試行回数などとともに一番つよいじゃんけんの手を教えてくれます。

勝敗を決める

じゃんけんを行う際に、3回勝負などで決着を付ける場合があります。しかしもはや3回では納得ができない場合に利用してください。
スクリーンショット 2020-01-04 23.34.07.png
例えばこの二者にじゃんけんをおこなわせると...

スクリーンショット 2020-01-04 23.35.43.png
こちらが勝利したようです。

回数を見る

こちらの画面ではいままでに行われたじゃんけんの総回数、最大回数、各手の勝利回数を見ることができます。それだけです。
スクリーンショット 2020-01-04 23.39.34.png

レッツじゃんけん!!!!

実際にどのように作成したか、どういったところに苦労したかなどは次回以降記述します。

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

ASP.NET Core のWebアプリケーションを Kubernetes で構築する

概要

(※) ASP.NET Core のWebアプリケーションを docker-compose で Dockerアプリケーション として構築する
の続編になります。

ASP.NET CoreのサンプルWebアプリケーションを題材として、Kubernetes の動作環境を構築する例を紹介します。

筆者は単なるアプリ屋ですが、「そろそろ Kubernetes に入門しておかないとヤバイかな…」と思い、
Kubernetes初心者ながら、本記事を書くに至りました。

Kubernetesの概念やリソース等は、ドキュメントや文献を参考にしつつ記載していますが、
間違いや不備があれば、ご指摘いただけると助かります。

環境

  • Windows10
  • Visual Studio 2019
  • ASP.NET Core 3.1
  • Docker for Windows

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

題材にしたサンプルアプリケーションです。
https://github.com/tYoshiyuki/dotnet-core-web-sample

docker-composeの際に利用したToDoのWebアプリケーションを今回も利用します。
トランザクションデータはデータベース (SQL Server) に保存しています。

システム構成

Docker for Windows を利用して、ローカルPC上にKubernetes環境を構築します。
ローカル開発時は、IIS Express と LocalDB で構成していました。これを、下記図のイメージで構築します。

image.png

「Nginx + ASP.NET Coreアプリケーション」 と 「SQL Server Express」 で2つのPodを作成します。

Podとは、Kubernetesにおけるコンテナ集合体の単位になります。
コンテナ単体では扱い辛いため、利用したいコンテナをグルーピングして利用するイメージになります。

次に、「Web + アプリケーション部分を担当する dotnet-core-web-sample」 と
「DB部分を担当する sqlexpress」 の2つのServiceを定義します。

Serviceは、Kubernetesクラスタ内において、Podに対してのアクセス経路を定義するリソースになります。

Kubernetesにおいて、コンテナが実際に動作する環境を Node と言います。
PodはNodeに対して分散配置されるため、Pod間で通信を行うことを考えた場合に、
Podの実IPアドレスを意識したアクセスを行うことは困難です。

そのため、Podに対するアクセスを抽象化して提供する仕組みが Service ということになります、

また、外部からのHTTPアクセス用に Ingress を導入します。
Ingressは、ServiceをL7層のレベルで外部に公開するためのリソースです。
今回は Nginx Ingress Controller を利用します。

解説

Docker for Windows の設定から、Kubernetesを有効化します。
image.png

またGUIツールとして、Visual Studio Codeの拡張機能を利用しました。
Kubernetesのリソースを視覚的に確認できるため、導入しておくと便利です。
image.png

1. app.yaml

まずは、Nginx、ASP.NET Coreアプリケーションの部分の定義を作成します。
Kubernetesのリソースは、YAMLで定義していきます。

app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dotnet-core-web-sample
  labels:
    app: dotnet-core-web-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dotnet-core-web-sample
  template:
    metadata:
      labels:
        app: dotnet-core-web-sample
    spec:
      containers:
      - name: web
        image: dotnet-core-web-sample_web
        imagePullPolicy: IfNotPresent
        env:
        - name: BACKEND_HOST
          value: localhost:5000  
        ports:
        - containerPort: 80
      - name: app
        image: dotnet-core-web-sample_app
        imagePullPolicy: IfNotPresent
        env:
        - name: ConnectionStrings__DefaultConnection
          value: "Server=sqlexpress;Database=master;User ID=sa;Password=P@ssw0rd;initial catalog=dotnetcorewebsample;MultipleActiveResultSets=True;App=EntityFramework;"
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: dotnet-core-web-sample
spec:
  selector:
    app: dotnet-core-web-sample
  ports:
  - name: http
    port: 80

前半部分はDeployment、後半部分はServiceの定義になります。

Deploymentは、Deployment > ReplicaSet > Pod というように、Podを管理するための上位概念になります。
ReplicaSetは、同じ仕様のPodを複数生成・管理するためのリソースになります。
Deploymentは、ReplicaSetを世代管理するためのリソースです。
本記事では触れませんが、デプロイ時のロールバックやRollingUpdateの機能を定義することが出来ます。

Podに配置するコンテナの定義は containers: の部分で記載しています。
Podで利用するdockerイメージは、前回の記事で作成したローカルのイメージを利用します。
imagePullPolicy: IfNotPresentを記載することで、ローカルイメージが存在する場合に、それを利用するようにしています。
dotnet-core-web-sample_webはNginxのdockerイメージ、dotnet-core-web-sample_appはASP.NET Coreのdockerイメージです。

各設定内容は docker-compose とほぼ同じですが、BACKEND_HOST に localhost:5000 を設定します。
これは、同一Podにおける宛先を localhost で解決出来るためです。

Serviceでは、dotnet-core-web-sampleという名称で、80番ポートを公開しています。

2. sqlexpress.yaml

次に、SQL Server Expressの定義です。

sqlexpress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sqlexpress
  labels:
    app: sqlexpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sqlexpress
  template:
    metadata:
      labels:
        app: sqlexpress
    spec:
      containers:
      - name: sqlexpress
        image: dotnet-core-web-sample_sqlexpress
        imagePullPolicy: IfNotPresent        
        env:
        - name: ACCEPT_EULA
          value: "Y"
        - name: MSSQL_PID
          value: Express
        - name: SA_PASSWORD
          value: P@ssw0rd
        ports:
        - containerPort: 1433
---
apiVersion: v1
kind: Service
metadata:
  name: sqlexpress
spec:
  selector:
    app: sqlexpress
  ports:
  - name: "1433"
    port: 1433
    targetPort: 1433

前半部分はDeployment、後半部分はServiceの定義になります。
構成内容としては、app.yamlとほぼ同様になっています。
Serviceでは、sqlexpressという名称で、SQL Server用の1433番ポートを公開しています。

3. Nginx Ingress Controllerの導入

Ingressを使用するために、Nginx Ingress Controllerを導入します。

Githubのドキュメントを参考にコマンドを実行します。
https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

ドキュメントには Docker for Mac と書かれていますが、Docker for Windowsでも大丈夫でした。

4. ingress.yaml

最後に、ingress.yamlを作成します。

ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dotnet-core-web-sample
spec:
  rules:
  - host: dotnetcorewebsample.local
    http:
      paths:
      - path: /
        backend:
          serviceName: dotnet-core-web-sample
          servicePort: 80

host: dotnetcorewebsample.localは、バーチャルホスト名になります。
path: /は、httpアクセス時のパス情報になります。

5. 動作確認

これまで作成してきた定義を、Kubernetesに適用させます。
kubectlコマンドを利用します。

> kubectl apply -f .\sqlexpress.yaml
deployment.apps/sqlexpress created
service/sqlexpress created

> kubectl apply -f .\app.yaml       
deployment.apps/dotnet-core-web-sample created
service/dotnet-core-web-sample created

> kubectl apply -f .\ingress.yaml
ingress.extensions/dotnet-core-web-sample created

稼働確認のため、hostsファイルに下記を記載します。

127.0.0.1 dotnetcorewebsample.local

ブラウザでアクセスすると、無事アクセスすることが出来ました。

image.png

まとめ

Kubernetesの概念は当初複雑に感じていましたが、実際に触ってみると理解が進み易いと感じました。
また、コンテナ技術を扱っている関係上、docker や docker-compose に慣れておくと入門し易いと思います。

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

Docker コンテナ内で立ち上げた godoc にホスト側からアクセスする

この記事について

Go言語の勉強用の環境として立ち上げた Docker コンテナ内で godoc サーバを立ち上げ、ホストOS側のブラウザからアクセスしてみたところ、アクセスできなかったので調べてみたメモ。

用意した Dockerfile

Dockerfile
FROM golang:latest

RUN mkdir /go/src/app
WORKDIR /go/src/app
RUN go get golang.org/x/tools/cmd/godoc
EXPOSE 6060/tcp

実行したコマンド1(godocがインストールされたコンテナのビルドと、そのコンテナでのgodocサーバの起動)

$ docker build -t hoge .
$ docker run --rm -p 6060:6060 hoge godoc

実行したコマンド2(ホストからgodocサーバにアクセス)

$ curl http://localhost:6060
curl: (52) Empty reply from server

上記のようにサーバから正常な応答が返ってこない。

上記のURLにアクセスした場合の期待する応答は、以下のようなリダイレクトのレスポンス。

$ curl -v http://localhost:6060
* Rebuilt URL to: http://localhost:6060/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6060 (#0)
> GET / HTTP/1.1
> Host: localhost:6060
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 302 Found
< Content-Type: text/html; charset=utf-8
< Location: /pkg/
< Date: Sat, 04 Jan 2020 12:58:12 GMT
< Content-Length: 28
<
<a href="/pkg/">Found</a>.

* Connection #0 to host localhost left intact

対処

godoc サーバを起動するコマンドを以下のように変更

$ docker run --rm -p 127.0.0.1:6060:6060 hoge godoc -http 0.0.0.0:6060
  • godoc の起動オプション -http 0.0.0.0:6060 を付与し、コンテナのすべてのネットワークインターフェースからの接続を受け付けるようにする。
  • docker run でコンテナ起動時に -p 172.0.0.1:6060:6060 のようにホスト側のネットワークインターフェースをローカル・ループバック・アドレスに限定する。
    • 別に -p 6060:6060 でもホストからアクセス可能だが、ホストと同じネットワークに存在する別の端末からもアクセス可能になってしまう。(参考
    • それでも構わない、あるいは、むしろ別端末アクセスさせたいというケースでは 172.0.0.1: の部分は省略しても構わない。

上記のようにサーバを起動したあと、ホスト側のブラウザから http://localhost:6060 にアクセスすると、無事 GoDoc のページが表示できた。

Image from Gyazo

参考

以下の記事がより詳しい

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

Docker コンテナ内で立ち上げた godoc にホスト側からアクセスできなかった

この記事について

Go言語の勉強用の環境として立ち上げた Docker コンテナ内で godoc サーバを立ち上げたが、ホストOS側のブラウザからアクセスできなかったので調べてみたメモ。

環境

用意した Dockerfile

Dockerfile
FROM golang:latest

RUN mkdir /go/src/app
WORKDIR /go/src/app
RUN go get golang.org/x/tools/cmd/godoc
EXPOSE 6060/tcp

実行したコマンド1(godocがインストールされたコンテナのビルドと、そのコンテナでのgodocサーバの起動)

$ docker build -t hoge .
$ docker run --rm -p 6060:6060 hoge godoc

実行したコマンド2(ホストからgodocサーバにアクセス)

$ curl http://localhost:6060
curl: (52) Empty reply from server

上記のようにサーバから正常な応答が返ってこない。

上記のURLにアクセスした場合の期待する応答は、以下のようなリダイレクトのレスポンス。

$ curl -v http://localhost:6060
* Rebuilt URL to: http://localhost:6060/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6060 (#0)
> GET / HTTP/1.1
> Host: localhost:6060
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 302 Found
< Content-Type: text/html; charset=utf-8
< Location: /pkg/
< Date: Sat, 04 Jan 2020 12:58:12 GMT
< Content-Length: 28
<
<a href="/pkg/">Found</a>.

* Connection #0 to host localhost left intact

対処

godoc サーバを起動するコマンドを以下のように変更

$ docker run --rm -p 127.0.0.1:6060:6060 hoge godoc -http 0.0.0.0:6060
  • godoc の起動オプション -http 0.0.0.0:6060 を付与し、コンテナのすべてのネットワークインターフェースからの接続を受け付けるようにする。
  • docker run でコンテナ起動時に -p 172.0.0.1:6060:6060 のようにホスト側のネットワークインターフェースをローカル・ループバック・アドレスに限定する。
    • 別に -p 6060:6060 でもホストからアクセス可能だが、ホストと同じネットワークに存在する別の端末からもアクセス可能になってしまう。(参考
    • それでも構わない、あるいは、むしろ別端末アクセスさせたいというケースでは 172.0.0.1: の部分は省略しても構わない。

上記のようにサーバを起動したあと、ホスト側のブラウザから http://localhost:6060 にアクセスすると、無事 GoDoc のページが表示できた。

Image from Gyazo

参考

以下の記事がより詳しい

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

過去の TeX Live の Docker コンテナ化

以前の記事では,最新の TeX Live 2019 に,高品質なオープンソース和文フォントである原ノ味フォントと,新進気鋭の LaTeX 文書ビルドシステム llmk を搭載した Docker コンテナのイメージを作成しました。

それに対し今回は,過去バージョンの TeX Live を保存した Docker コンテナを作成してみました。

使い道

過去バージョンの TeX Live を Docker コンテナとして保存し,いつでも過去バージョンを呼び出せるようにしておくと,次のような場面で役立つはずです。

  • 過去に組版した文書を今コンパイルしたら組版結果があちこち変わり,ページ数が変わってしまった!(←これ結構起こりますよね……?)元と同じ環境で再度コンパイルしたい……!
  • 最新の TeX Live だとコンパイルが通らない。昔のバージョンではこのソースで通っていたはず。どの時点の TeX Live まではコンパイルが通っていたのかをさかのぼって検証したい。
  • Web 上で「TeX Live 2015 で組版したところ結果が期待通りになりません」といった質問に答えるにあたり,手元で検証して動作を確認したい。

仕様

日本語 TeX 開発コミュニティ (texjp.org) のサーバから取得した,次の各 TeX Live の frozen 版 (scheme-full) をコンテナイメージとして固めました。それぞれ Ubuntu 18.04 ベースです。Ubuntu 18.04 公式レポジトリの Ghostscript 9.26 も同梱・設定されています。

  • TeX Live 2012 (frozen)
  • TeX Live 2013 (frozen)
  • TeX Live 2014 (frozen)
  • TeX Live 2015 (frozen)
  • TeX Live 2016 (frozen)
  • TeX Live 2017 (frozen)
  • TeX Live 2018 (frozen)

IPAex フォント埋め込み設定

各バージョンとも,(u)pLaTeX + dvipdfmx/dvips を使った場合にデフォルトで IPAex フォントを埋め込む設定を済ませてあります。

llmk 同梱

TeX Live とは別に,/usr/local/binllmk を入れ,Docker コンテナを引数なしで起動したときに llmk が呼び出されるようにしてあります。(ただし TeX Live 2012 の texlua では llmk を動かせなかったので入れていません。)

Docker Hub レポジトリ

次の各タグでバージョンが区別されています。

  • 2012frozen
  • 2013frozen
  • 2014frozen
  • 2015frozen
  • 2016frozen
  • 2017frozen
  • 2018frozen

使い方

イメージの pull

まず,使いたいバージョンのタグを指定して pull します。

$ docker pull doratex/tlarchive:2015frozen

起動法

コンテナ内では /workdir が作業ディレクトリとなるので,それをカレントディレクトリと bind マウントして使うのを想定しています。

alias tl2015="docker run --rm \
  --mount type=bind,src=\"\$(pwd)\",dst=/workdir \
  --mount type=volume,src=ltfontcache2015,dst=/usr/local/texlive/2015/texmf-var/luatex-cache/generic/fonts/otl \
  doratex/tlarchive:2015frozen"

などとエイリアスを設定しておくと楽でしょう。(--mount type=volume,... の部分は,LuaTeX のフォントキャッシュを ltfontcache2015 というボリューム(名前は任意です)に保存し永続化させるための設定です(詳細は前回の記事を参照)。このエイリアスが設定されている下で

$ tl2015 ptex2pdf -l hoge.tex
$ tl2015 lualatex fuga.tex

などと普通にコンパイルすることも可能です。pLaTeX + dvips + ps2pdf のワークフローを使う場合は,

$ tl2015 /bin/bash -c 'platex hoge.tex && dvips hoge.dvi && ps2pdf hoge.ps'

とすれば OK です。

(u)pLaTeX + dvipdfmx/dvips においては,デフォルトで IPAex フォントを埋め込む設定になっています。

また,引数なしで

$ tl2015

と起動すると,同梱の llmk が動き,カレントディレクトリの llmk.toml に基づきビルドしようとします。

$ tl2015 llmk hoge.tex

のようにして特定のファイルをターゲットにすることもできます。従来の latexmk もインストールされているので

$ tl2015 latexmk hoge.tex

も使えます。

Dockerfile

このイメージを作るために使用した Dockerfile は GitHub レポジトリに置いてあります。年号が違う以外はほぼ同様に見えますが,各バージョンの仕様の違いに応じて以下のように微調整してあります。

  • install-tl-repositoryhttps に対応したのは TeX Live 2017 以降なので,TeX Live 2016 以前では http を使う。
  • TeX Live 2012 では kanji-config-updmap-sys ではなく updmap-setup-kanji-sys を使う。
  • TeX Live 2012 では luaotfload-tool がないので TEXMFDIST/scripts/luaotfload/mkluatexfontdb.lua を直接呼び出す。
  • TeX Live 2012 では llmk が動かないのでインストールしない。

イメージサイズ

scheme-full で TeX Live を丸ごとコンテナ化しているイメージサイズは大きいです。それにしても,こうやって並べてみると,TeX Live の全体サイズが年々肥大化しているのが分かりますね……。

REPOSITORY TAG SIZE
doratex/tlarchive 2012frozen 1.90 GB
doratex/tlarchive 2013frozen 2.03 GB
doratex/tlarchive 2014frozen 2.27 GB
doratex/tlarchive 2015frozen 2.38 GB
doratex/tlarchive 2016frozen 2.68 GB
doratex/tlarchive 2017frozen 2.94 GB
doratex/tlarchive 2018frozen 3.22 GB

参考文献

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

(ユーザ定義の) Docker Networkチートシート

何回も調べなおしているのでメモを兼ねて
(特にdocker-composeでのネットワーク指定パターン)

ネットワークの作成方法

docker network create -d bridge --gateway=192.168.0.1 --subnet=192.168.0.0/16 <ネットワーク名>

docker run時の指定方法

docker run --net=<ネットワーク名>

Docker composeからの利用方法

IPアドレスを指定して使う

services:
  my-service:
    ~~~
    networks:
      default:
        ipv4_address: 192.168.0.1

networks:
  default:
    external:
      name: <ネットワーク名>

IPアドレス自動割り当てで使う

services:
  my-service:
    ~~~
    networks:
      - <ネットワーク名>

networks:
  <ネットワーク名>:
    external: true
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker で作ったWebサーバ(app.py by Flask)を動かすテスト

Docker を使って、GCPを使って、いろいろやりたいなー、と思っていましたが、冬休みももう終わりそうです。

Docker の使い方がメインで、できたのは以下です。

  1. Dockerfile を書く
  2. Docker image を作る (docker build)
  3. ローカルで動かす (docker run)
  4. ローカルで確認 (localhost をWEBブラウザで見る)

サーバとして動いているのは、下記のContainer で動いているものです。

mydockerimage20190104.png

1. Dockerfile とsource file の用意

こんなDockerfileを作りました。

# our base image
FROM ubuntu

# Install python and pip
RUN apt update -y
RUN apt install python3  -y -qq --no-install-recommends 
RUN apt install python3-pip -y -qq  --no-install-recommends
RUN pip3 install --upgrade pip

# install Python modules needed by the Python app
COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt

# copy files required for the app to run
COPY app.py /usr/src/app/
COPY templates/index.html /usr/src/app/templates/

# tell the port number the container should expose
EXPOSE 5000

# run the application
CMD ["python3", "/usr/src/app/app.py"]

Dockerfile では、

  • ubuntu をbase image にして作る
  • python3 と pipをインストールする
  • app.py をコピーする
  • 最後にCMD で実行する

と読めます。Dockerfile が置いてあるディレクトリをもとにimage を構成しています。実際のファイルはここからダウンロードできます。

2. Docker Image を作る

> docker build --no-cache -t myapp .

最後にこんなメッセージが。Windows での権限の設定の仕方はいまだに分かりませんが、今のところ問題にはなっていません。

Successfully tagged myapp:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

3. ローカルで動かす

> docker run -it --rm -p 8001:8000 myapp
* Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 335-299-345
172.17.0.1 - - [03/Jan/2020 13:14:11] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [03/Jan/2020 13:14:11] "GET /favicon.ico HTTP/1.1" 404 -

仮想化したこのマシンが動いているかはdocker コマンドで確認できます。

> docker ps

4. Webブラウザで確認

普通にlocalhost:8001 を開くと見えると思います。あるいは以下でも。

$curl http://localhost:8001

StatusCode        : 200
StatusDescription : OK
Content           : <!-- index.html -->
                    <!DOCTYPE html>
                    <html lang="ja">
                      <head>
                      </head>
...

備忘録

この後、デプロイして?ほかのクラウドサーバで動かしたいのですが、そこまでできていないので、続きをこれから頑張ります。また、Flaskも情報が思いのほか多いのでもう少し何かできるかも。

テストコード

できた部分は、ここだけ切り取ってGithubのsamplesのここに置きました。samples/docker-python-flask-20200104 というディレクトリにあります。下記の参考サイトをもとに編集して辿り着いたものです。

参考

できればこのイメージを内部、あるいは外部のサーバで動かしたい。

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

Go1.13とDockerで開発環境構築(ホットリロード有)

はじめに(背景)

筆者は今までGoでは簡単なツール(Slack用Botとか)しか作ってこなかったが、
Goを使ってWEBアプリを開発してみることにした。 

ところが、開発環境を構築するのに、検索でヒットする情報が微妙だった
- Goのバージョンが古くてGo Modulesを使っていなかったり、
- 使っているライブラリの最終更新が3年前だったり

情報を整理しながら開発環境を構築する必要が有ったので、
せっかくだからアウトプットしておこうと思った。

前提

  • Goのversionは、執筆時点で最新の1.13系を使う
  • docker-composeで立ち上げたい
  • せっかくなので、ホットリロードが欲しい

以下には触れません

  • GoでのWEBサーバーの立ち上げ方
  • Go Modulesについて
  • Docker、docker-composeの使い方

本題

Goの設定

Go Modulesを使う

Go Modulesの導入や使い方などは割愛
↓のコマンドでinitialize
go mod init github.com/username/project

ホットリロードの設定

色々調べたら、Realizeが良さそう(適当)
https://github.com/oxequa/realize

設定ファイル(後述)を用意して、
realize startコマンドを実行するだけ

Docker環境用意

Dockerfile

FROM golang:1.13-alpine

WORKDIR /app

COPY . .

RUN apk add --no-cache git \
  && go get gopkg.in/urfave/cli.v2@master \
  && go get github.com/oxequa/realize

 
.realize.yml (ホットリロードの設定)

settings:
  legacy:
    force: false
    interval: 0s
schema:
- name: hoge
  path: path/to/server
  commands:
    install:
      status: true
    run:
      status: true
  watcher:
    extensions:
    - go
    paths:
    - path/from/server
    ignore_paths:
    - .git

 
docker-compose.yml

version: "3"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    volumes:
      - ./:/app
    command: realize start

 

※realizeの設定でエラーが出た。(↑のファイルには反映済み)

パッケージを取得する時
解決方法は以下のissueから
https://github.com/oxequa/realize/issues/253
↓の箇所

RUN apk add --no-cache git \
  && go get gopkg.in/urfave/cli.v2@master \
  && go get github.com/oxequa/realize

 

Go Modules環境起因でもエラー
以下のissueから
https://github.com/oxequa/realize/issues/217
↓の箇所

  commands:
    install:
      status: true

おわりに

以上で、DockerでGoを開発する環境ができました。
あとはdocker-composeにDBなり何なりを追加すれば進められそうです。

 

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

GKEで自作コンテナのRails6を起動する

はじめに

Rails6プロジェクトの新規作成からGKE上で動作させるまでを試した結果となります。
今回試したのは以下3点です。
- Dockerイメージ(Ruby公式 2.7.0)から新たにRails6用Dockerイメージを作成する
- 作成したDockerイメージをDockerHubへ登録
- DockerHubに登録したイメージを使ってGKEのノードを作成し起動する

手順

1.Dockerイメージの取得

$ docker pull ruby:2.7.0

2.プロジェクトディレクトリ、Gemfileの作成

$ mkdir project_name
$ cd project_name
$ docker run --rm -v "$PWD":/usr/src/project_name -w /usr/src/project_name ruby:2.7.0 bundle init

3.Gemfileの編集

以下のコメント箇所を外したくらいです

Gemfile
#gem 'rails'

4.Dockerファイルの用意

Docerfileの内容については以下の記事を参考にさせて頂きました。
https://qiita.com/togana/items/30b22fc39fe6f7a188ec

今回の主な変更点は以下の点になりました

  • yarnのリポジトリ設定(Rails6の起動にはwebpackerが必要で、Webpackerのインストールにはyarnが必要)
  • yarnのインストール(上記と同じ理由)
  • webpackerのインストール
Dockerfile
FROM ruby:2.7.0

ENV APP_ROOT /usr/src/rails6-base
WORKDIR $APP_ROOT

# yarnのリポジトリ設定(Rails6の起動の為に必要)
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

# packageリストの更新
RUN apt-get update

# packageからのインストール
RUN apt-get install -y \
      nodejs \
      default-mysql-client \
      sqlite3 \
      yarn \
      --no-install-recommends

# packageインデックスファイルの削除
RUN rm -rf /var/lib/apt/lists/*

# Gemのインストール
COPY Gemfile $APP_ROOT
COPY Gemfile.lock $APP_ROOT
RUN \
  echo 'gem: --no-document' >> ~/.gemrc && \
  cp ~/.gemrc /etc/gemrc && \
  chmod uog+r /etc/gemrc && \
  bundle config --global build.nokogiri --use-system-libraries && \
  bundle config --global jobs 4 && \
  bundle install && \
  rm -rf ~/.gem

# webpackerがないとRails6を起動できないので
RUN bundle exec rails webpacker:install

COPY . $APP_ROOT

# 3000ポートをListern状態で起動
EXPOSE  3000
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

5. railsプロジェクトの新規作成

Dockerイメージを作成する時にプロジェクトのファイルをイメージにコピーするので必要。

$ docker run --rm -it -v "$PWD":/usr/src/sample-ruby-gke developer_name/project_name bundle exec rails new .

6.Dockerイメージの生成

$ docker build -t developer_name/project_name .

7.Dockerイメージからコンテナの生成と起動

$ docker run -d -p 3000:3000 developer_name/project_name

8.ブラウザからアクセスする

ブラウザから以下のURLにアクセスしてRailsの画面が表示されることを確認
http://localhost:3000/

9.DockerHubへの登録

$ docker login
$ docker push developer_name/project_name:latest

DockerHubに登録ができたかは以下URLで確認できる
https://hub.docker.com/

10.DockerHubに登録されたDockerイメージからGKEノードを作成

以下、GCP Console画面です。
Kubernetes Engine -> ワークロード -> デプロイを選択すると以下の画面が表示されます。
スクリーンショット 2020-01-04 15.27.06.jpg
以下を選択し、後はデフォルトのままとしました。

  • 「既存コンテナイメージ」を選択
  • イメージパス:developer_name/project_name:latest (上記で作成しDockerHubに登録したものと同じものを選択)

11.GKEのサービスを作成し外部公開する

ポートを3000に設定した他は前回の4の手順以降と同じです。
https://qiita.com/bleu/items/f2f16ee34fb0039e8890

参考

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

フロントNuxt.js - バックDjango間のAPI連携を実装してみた

初めに

初投稿です。
最近Web系の開発に興味があり、色々勉強しています。
この記事では、バックエンドの部分をDjangoで、
フロントエンドの部分をNuxt.jsで作成したものについて、
とりあえず開発環境で動くもので書いていきます。

準備

下記イメージを元にdocker-composeを使ってそれぞれの環境を構築
qiita用1 (2).jpg

環境

Window10 Pro
Docker desktop v2.1.0.5
Python 3.6.9
django 2.2.7
djangorestframework 3.10.3
MySQL Ver 8.0.17
Nuxt.js v2.11.0

ディレクトリ構造

.
├─django
│  ├─manage.py
│  ├─composeexample
│  │   ├─settings.py
│  │   ├─urls.py
│  │   ├─wsgi.py
│  │   └─__init__.py
│  └─myapp
│      ├─migrations
│      ├─admin.py
│      ├─apps.py
│      ├─models.py
│      ├─renderers.py
│      ├─serializers.py
│      ├─tests.py
│      ├─urls.py
│      ├─views.py
│      └─__init__.py
│
├─docker-compose.yml
│
├─dockerfiles
│  ├─django_docker
│  │   ├─dockerfile
│  │   └─requirements.txt
│  └─nuxt_docker
│      └─dockerfile
│
├─mysql
│  └─conf.d
│
└─nuxt
    └─front
       └─以下略

各種ファイル

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

services:
  db:
    image: mysql:latest
    restart: always
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: test
      MYSQL_USER: test
      MYSQL_DATABASE: test
      MYSQL_PASSWORD: test
    ports:
      - 3306:3306
    expose:
      - 3306
    volumes:
      - mysqldata:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d

  web:
    container_name: django
    build: ./dockerfiles/django_docker
    command: 
      python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - ./django:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

  front:
    container_name: nuxt
    build: ./dockerfiles/nuxt_docker 
    tty: true
    volumes:
      - ./nuxt:/code
    ports:
      - "3000:3000"

volumes:
  mysqldata:
./dockerfiles/django_docker/dockerfile
# ベースイメージを指定
FROM python:3.6-stretch

ENV PYTHONUNBUFFERED 1
RUN mkdir /code

# ディレクトリを移動する
WORKDIR /code

# pipでrequirements.txtに記載のパッケージをインストール
COPY requirements.txt /code/
RUN pip3 install -r requirements.txt

COPY . /code/

※djangoのイメージはOpen SSHの鍵長の関係でstretchでbuildしてます。こちら参照

./dockerfiles/django_docker/requirement.txt
Django>=2.0,<3.0
djangorestframework
django-webpack-loader
django-cors-headers
mysqlclient

※requierment.txtに必要となるpythonのパッケージを記載します。
 Djangoだけでなく、今回APIに必要なパッケージも入れます。

 以下はDjango REST frameworkに必要なもの
 ・djangorestframework
 ・django-webpack-loader
 ・django-cors-headers

 また以下はMySQLをDjangoから使うのに必要なもの
 ・mysqlclient

./dockerfiles/nuxt_docker/dockerfile
# ベースイメージを指定
FROM node:latest

RUN mkdir -p /code

# node.js の環境変数を定義する
# 本番環境では production
ENV NODE_ENV=development

# yarnとaxiosをinstall
RUN yarn install
RUN yarn add @nuxtjs/axios

# ディレクトリを移動する
WORKDIR /code

# ポート3000番を開放する
EXPOSE 3000

djangoの構築

プロジェクトの作成

こちらの記事を参考にしてます。
Djangoを最速でマスターする part1
DockerでDjangoの開発環境を作成する(Quickstart: Compose and DjangoのMySQL版)
【Django】アプリケーションの追加手順
まずdocker-composeでコンテナを立ち上げます。MySQLから建てます。

> docker-compose up -d db

docker ps で確認

> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
285cf6b8473b        mysql:latest        "docker-entrypoint.s…"   2 minutes ago       Up 4 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   mysql

続いてdocker-composeでコンテナを立ち上げます。初回なのでbuildもしておきます。

> docker-compose up -d --build

Djangoのプロジェクトを作ります。(プロジェクト名は任意です)

> docker-compose run web django-admin.py startproject composeexample .

この部分が生成されます。

.
└─django
   ├─manage.py
   └─composeexample
       ├─settings.py
       ├─urls.py
       ├─wsgi.py
       └─__init__.py

続いてsetting.pyを編集します。
デフォルトではSQLiteを使用するようになっているので、これをMySQLに変更します。

#<変更前>
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

#上記を↓↓↓に変更
#ユーザ名やパスは適宜変更してください

#<変更後>
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'USER': 'test',
        'PASSWORD': 'test',
        'HOST': 'db',   
        'PORT': '3306',
    }
}

次は連携したDBのマイグレーションを行います。

> docker-compose run web ./manage.py migrate

スーパユーザを作成します。

> docker-compose run web ./manage.py createsuperuser --username admin --email admin@localhost
Starting mysql ... done                                                                                   
Password: #パスワードを聞かれるので入力
Password (again): #再度入力
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common. #パスワードが短いと警告が出る
Bypass password validation and create user anyway? [y/N]: y #yを入力
Superuser created successfully.

ここで一度djangoの開発用サーバを起動してみます。
docker-compose up -dでdocker-compose.ymlに記載したコンテナが全てバックグラウンドで起動します。
(Nuxtのコンテナもこの段階で起動しています)

> docker-compose up -d

> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                         NAMES
746b29edf07b        working_web         "python3 manage.py r…"   30 hours ago        Up 30 hours         0.0.0.0:8000->8000/tcp                        django
0ae9f6506532        mysql:latest        "docker-entrypoint.s…"   30 hours ago        Up 30 hours         3306/tcp, 33060/tcp, 0.0.0.0:3306->3306/tcp   mysql
0107b2a7301b        working_front       "docker-entrypoint.s…"   30 hours ago        Up 30 hours         0.0.0.0:3000->3000/tcp                        nuxt

django開発用サーバはポート8000で待ち受けているので、
http://localhost:8000/admin にアクセスしてみます。
./docker-compose.ymlの下記に該当します。

./docker-compose.yml
#~略~
    command: 
      python3 manage.py runserver 0.0.0.0:8000
#~略~

下記画面が出れば成功です。(Chromeの拡張入れているので背景が黒いです)
image.png

作成したスーパユーザでログインしてみます。
デフォルトでは2つのユーザが作られていることがわかります。
image.png

アプリの作成

続いてアプリ部分を生成します。(アプリ名は任意です)

> docker-compose run web ./manage.py startapp myapp

この部分が生成されます。

.
└─django
   └─myapp
       ├─migrations
       ├─admin.py
       ├─apps.py
       ├─model.py
       ├─tests.py
       ├─view.py
       └─__init__.py

setting.pyに作成したアプリを追記します。
これをしないとdjango上で生成したアプリが認識されません。

./django/composeexample/setting.py
# ~略~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', #追加
]
# ~略~

生成されたmodels.pyにモデルを追記していきます。
とりあえず簡易なPerson_dataモデルを作成します。
人の名前と年齢のみを保持したものです。
ここに記載し、マイグレーションをすることでMySQL上にテーブルが作成されます。

./django/myapp/models.py
from django.db import models

# Create your models here.
class Person_data(models.Model):
    person_name = models.TextField()
    person_age = models.IntegerField()

下記でマイグレーションを行います。
アプリを追加した場合はmakemigrationsが必要です。

> docker-compose run web ./manage.py makemigrations
> docker-compose run web ./manage.py migrate

admin.pyに下記を追記することで、管理画面から作成したモデルを確認できます。

./django/myapp/admin.py
from django.contrib import admin
from .models import Person_data #作成したモデルをimport

# Register your models here.
admin.site.register(Person_data) #作成したモデルを追記

MYAPPとPerson_datasが追加されています。
image.png

+ADDをクリックするとデータ追加画面が開きます。
SAVEで追加できます。
image.png

適当にデータを追加していくと下記のように行が増えていきます。
image.png

下記でMySQL上でも確認できます。

> docker exec -it mysql /bin/bash #MySQLコンテナに入る

> mysql -u test -p #MySQL起動
Enter password: #本記事の例だとtestでログイン可能

> use test;
> select * from myapp_person_data;
+----+-------------+------------+
| id | person_name | person_age |
+----+-------------+------------+
|  1 | takashi     |         26 |
|  2 | naoto       |         32 |
|  3 | tomoko      |         15 |
+----+-------------+------------+
3 rows in set (0.00 sec)

ここまででdjangoの準備は完了です。

Django REST frameworkの構築

Djangoの準備ができたところで、次はDjango側にAPIを作っていきます。
GETで上記テーブルの中身を取得するだけの簡易なものを作成します。
まずはsetting.pyに追記していきます。

ここはこちらを参考にしています。
Django REST frameworkでAPIを作ってみた
Django REST Framework で API サーバーを実装して得た知見まとめ(OAuthもあるよ)

./django/composeexample/setting.py
# ~略~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', 
    'rest_framework', #追加
]
# ~略~

'rest_framework'を追記することで、Django REST frameworkの機能を使用できるようになります。
続いて、Serializer.pyとRenderer.pyとurls.py(myapp配下)を手動で新規作成し、下記内容を追記します。

.
└─django
   └─myapp
       ├─migrations
       ├─admin.py
       ├─apps.py
       ├─model.py
       ├─tests.py
       ├─view.py
       ├─renderers.py #これ
       ├─serializers.py #これ
       ├─urls.py #これ
       └─__init__.py
./django/myapp/serializers.py
from rest_framework import serializers
from .models import Person_data

class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        model = Person_data
        fields = '__all__' 
./django/myapp/renderers.py
import json
from rest_framework.renderers import JSONRenderer

class PersonJSONRenderer(JSONRenderer):
    charset = 'utf-8'  

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return json.dumps({'person_data': data},ensure_ascii=False)
./django/myapp/urls.py
from django.urls import path
from .views import PersonListApiView


urlpatterns = [
    path('get_person/', PersonListApiView.as_view()),
]

composeexample配下のurls.pyを編集し、myapp配下のurls.pyを有効にします。

./django/composeexample/urls.py
"""composeexample URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include # includeを追加

from myapp import urls # myapp配下のurls.pyをimport


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(urls), # 追加
]

view.pyを編集します。

./django/myapp/views.py
from django.shortcuts import render
from django.views.generic import ListView

from myapp.models import Person_data

from rest_framework import status
from rest_framework.generics import ListAPIView
from rest_framework.permissions import AllowAny

from .renderers import PersonJSONRenderer
from .serializers import PersonSerializer

# Create your views here.

class PersonListApiView(ListAPIView):
    model = Person_data # モデルを指定
    queryset = Person_data.objects.all()
    permission_classes = (AllowAny, )
    renderer_classes = (PersonJSONRenderer, ) # Rendererを指定
    serializer_class = PersonSerializer # Serializerを指定

settings.pyに下記を追記します。

./django/composeexample/settings.py
REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

http://localhost:8000/api/get_person/ を叩いてみます。
結果をjsonで取得てきていれば成功です。
image.png

Nuxt.jsからAPIの結果を取得する

django側のAPIができたので、フロント側を作成していきます。
こちら参考にしてます。
Nuxt.js・Vue.js の基本的な使い方を理解する
Nuxt.js公式サイト

まずnuxt.jsのコンテナに入り、プロジェクトを作成します(プロジェクト名は任意です)。

yarn create nuxt-app frontを入力後の選択肢は基本全てデフォルト値を入れていますが、
rendering modeだけSingle Page Appを指定しました。
ここでの設定はあとでnuxt.config.jsというファイルから変更可能です。

> docker exec -it nuxt /bin/bash

> yarn create nuxt-app front

? Project name front
? Project description My doozie Nuxt.js project
? Author name
? Choose the package manager Yarn
? Choose UI framework None
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose test framework None
? Choose rendering mode Single Page App
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)

下記は表示されれば完了です。

?  Successfully created project front

  To get started:

        cd front
        yarn dev

  To build & start for production:

        cd front
        yarn build
        yarn start

Done in 167.32s.

確認のために開発用サーバを動かす前に、nuxt.config.jsに追記します。
docker上でnuxt.jsを動かす際は下記が必要です。
こちら参考

./nuxt/front/nuxt.config.js
export default {
  mode: 'spa',

  //ここから
  server: {
    port: 3000,
    host: '0.0.0.0',  
  },
  //ここまでを追記

  /*
  ** Headers of the page
  */

開発用サーバを動かしてみます。
完了後のメッセージにも記載されていますが、コンテナ内で作成したプロジェクトのフォルダに移動して、
yarn devです。

> cd front
> yarn dev

http://localhost:3000/ にアクセスしてみます。
下記表示であれば成功です。
image.png

ここから編集していく際にホットリロードを有効にします。
docker上で開発するためには明示的に指定が必要です。
こちら参考
下記をファイル末尾に追記します。

./nuxt/front/nuxt.config.js
export default {
//~略~
  }, //追記の際はこのカンマを忘れずに
  watchers: {
    webpack: {
      poll: true
    }
  }
}

続いてaxiosの設定を追記していきます。
axiosはnode.jsで動くHTTPクライアントで、これを利用してnuxt.jsから先ほどのAPIのURLを叩きます。
前述のnuxtのdockerfileに記載してあるので、すでにコンテナにはインストール済です。
modulesに下記を追記、及びaxiosを追加します。
axios

./nuxt/front/nuxt.config.js
export default {
//~略~
  modules: [
    '@nuxtjs/axios',
  ],
  axios: {
    baseURL: "http://localhost:8000"
  },
//~略~

次に実際のページの編集をしていきます。
今回は簡便にするために、indexを編集していきます。

./nuxt/front/pages/index.vue
<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        front
      </h1>
      <h2 class="subtitle">
        My doozie Nuxt.js project
      </h2>
      <div class="links">
        <a
          href="https://nuxtjs.org/"
          target="_blank"
          class="button--green"
        >
          Documentation
        </a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey"
        >
          GitHub
        </a>

<!-- ここから追記 -->
        <div v-for="d in dat.person_data" :key=d.person_name align="center">
          <h2>
            {{d.person_name}} {{d.person_age}} 
          </h2>
        </div>
<!-- ここまで追記 -->

      </div>
    </div>
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },

//ここから追記
  data() {
    return {
      dat: []
    }
  },
  async mounted(){
    const url = "/api/get_person/" 
    const response = await this.$axios.get(url)
    this.dat = response.data
  }
//ここまで追記
}
</script>
//~略~

このままではCORSにひっかかるので、django側の設定をいじります。
setting.pyに追記します。

./django/composeexample/setting.py
# ~略~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', 
    'rest_framework', 
    'corsheaders', #追加
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware', # 追加
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ~略~

### 末尾に下記を追加

# 許可するオリジン
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',
]
# レスポンスを公開する
CORS_ALLOW_CREDENTIALS = True

下記のようにAPI経由で先ほどテーブルに入れたデータが取得できています。
image.png

おわりに

以上でAPI経由でのdjangoとNuxt.jsの簡単な連携ができました。
上記は開発環境のものなので、本番用にまたチューニングする必要があるかと思いますが、
勉強のため一度この段階で投稿させていただきました。

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

Echo+GORMでRESTfulなAPIサーバをつくる

Overview

小規模なプロダクトにおいてPythonでAPIサーバはしんどい(できるけどソースが美しくない)ので, 全然使ったことないけどGoでAPIサーバを立ててみたい

Description

普段お仕事ではDjango REST Framework, 趣味ではFlaskを使っているんですが, PythonでORマッパー使おうとするとSQLAlchemyとか使うハメになってしんどいです.

かといってDjangoを使うのはウェイトが重い...
peeweeとかいういい感じのライブラリもあるっぽいですが

ということでせっかくなのでGoで作ってみます

今回は, 要素を一意に特定できるidと文字列textを要素に持つPostを定義して, API経由でCRUD操作を行うようなアプリを作ります

GET: localhost:1323/posts -> 全postの取得
GET: localhost:1323/posts/:id -> id指定でpost取得
PUT: localhost:1323/posts/:id -> id指定でpost更新
POST: localhost:1323/posts/:id -> id指定でpost作成
DELETE: localhost:1323/posts/:id -> id指定でpost削除

Settings

DockerでGoの開発環境を整えます

とりあえず動かしたいという方は後述のソースをまるっとコピりましょう

環境構築について, こちらの記事がわかりやすいです.
Golang(Echo) x docker-composeでホットリロード用いた開発

ディレクトリ構造

.
├── Dockerfile
├── docker-compose.yml
└── src
    ├── main.go
    ├── go.mod
    ├── go.sum
    ├── controller
    │   └── sqlite.go
    └── view
        └── post.go

プログラム本体

ディレクトリ構造に合わせてコピる

main.go

GET, POST, PUT, DELETEなど各メソッドを使える

package main

import (
    "github.com/labstack/echo"
    view "app/view"
)

func main() {
    e := echo.New()
    initRouting(e)
    e.Logger.Fatal(e.Start(":1323"))
}

func initRouting(e *echo.Echo) {
    e.GET("/posts", view.GetAllPosts)
    e.GET("/posts/:id", view.GetPost)
    e.POST("/posts", view.CreatePost)
    e.PUT("/posts/:id", view.UpdatePost)
    e.DELETE("/posts/:id", view.DeletePost)
}

post.go

json:idでレスポンスのjsonのキー名を指定できる. デフォだとPascalCaseになっちゃうのがウザいので設定

gorm:hogeで各属性を指定できる

これDB接続のところDecoratorみたいな感じで綺麗に共通化できないんでしょうか...
詳しい方教えて下さい

package view

import (
    "net/http"
    "github.com/labstack/echo"
    . "app/controller"
)

type Post struct {
    Id int `json:"id" gorm:"primary_key;AUTO_INCREMENT"`
    Text string `json:"text"`
}

func GetAllPosts(c echo.Context) error {
    db := OpenSQLiteConnection()
    defer db.Close()
    db.AutoMigrate(&Post{})

    var posts []Post
    db.Find(&posts)
    return c.JSON(http.StatusOK, posts)
}

func GetPost(c echo.Context) error {
    db := OpenSQLiteConnection()
    defer db.Close()
    db.AutoMigrate(&Post{})

    if id := c.Param("id"); id != "" {
        var post Post
        db.First(&post, id)
        return c.JSON(http.StatusOK, post)
    } else {
        return c.JSON(http.StatusNotFound, nil)
    }
}

func CreatePost(c echo.Context) error {
    db := OpenSQLiteConnection()
    defer db.Close()
    db.AutoMigrate(&Post{})

    post := new(Post)
    if err := c.Bind(post); err != nil {
        return err
    }
    db.Create(&post)

    return c.JSON(http.StatusOK, post)
}

func UpdatePost(c echo.Context) error {
    db := OpenSQLiteConnection()
    defer db.Close()

    newPost := new(Post)
    if err := c.Bind(newPost); err != nil {
        return err
    }

    if id := c.Param("id"); id != "" {
        var post Post
        db.First(&post, id).Update(newPost)
        return c.JSON(http.StatusOK, post)
    } else {
        return c.JSON(http.StatusNotFound, nil)
    }

}

func DeletePost(c echo.Context) error {
    db := OpenSQLiteConnection()
    defer db.Close()

    if id := c.Param("id"); id != "" {
        var post Post
        db.First(&post, id)
        db.Delete(post)
        return c.JSON(http.StatusOK, post)
    } else {
        return c.JSON(http.StatusNotFound, nil)
    }
}

sqlite.go

hoge.sqlite3はDBを保存したいパスを指定
:memory: の方を使うとインメモリで使える

package controller

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/sqlite"
)

func OpenSQLiteConnection() *gorm.DB {
    //db, err := gorm.Open("sqlite3", ":memory:")
    db, err := gorm.Open("sqlite3", "hoge.sqlite3")
    if err != nil {
        panic("failed to connect database.")
    }

    db.LogMode(true)
    return db
}

Docker関連ファイル

libc-dev, gccがないとrealize(ホットリロード用ライブラリ)がインストールできないのでインスコ

Dockerfile

FROM golang:1.13.5-alpine as build

WORKDIR /go/app

COPY src .

RUN apk add --no-cache git gcc libc-dev \
 && go build -o app \
 && go get gopkg.in/urfave/cli.v2@master \
 && go get github.com/oxequa/realize

FROM alpine

WORKDIR /app

COPY --from=build /go/app/app .

RUN addgroup go \
  && adduser -D -G go go \
  && chown -R go:go /app/app

CMD ["./app"]

docker-compose.yml

version: '3.5'

services:
  app:
    build:
      context: .
      target: build
    volumes:
      - ./src:/go/app
    command: realize start --run --no-config
    ports:
      - 1323:1323

Run

モジュール管理用ファイルのgo.modを生成

$ docker run --rm -v `pwd`:/go/app -w /go/app golang:1.13.5-alpine go mod init app

各ファイルを作り終わったら次のコマンドでイメージのビルド&実行

$ docker-compose build
$ docker-compose up

~
app_1  | [02:18:27][APP] : Install started
app_1  | [02:18:28][APP] : Install completed in 0.446 s
app_1  | [02:18:28][APP] : Running..
app_1  | [02:18:28][APP] :    ____    __
app_1  | [02:18:28][APP] :   / __/___/ /  ___
app_1  | [02:18:28][APP] :  / _// __/ _ \/ _ \
app_1  | [02:18:28][APP] : /___/\__/_//_/\___/ v3.3.10-dev
app_1  | [02:18:28][APP] : High performance, minimalist Go web framework
app_1  | [02:18:28][APP] : https://echo.labstack.com
app_1  | [02:18:28][APP] : ____________________________________O/_______
app_1  | [02:18:28][APP] :                                     O\
app_1  | [02:18:28][APP] : ⇨ http server started on [::]:1323

コンテナができたらプログラムが実行されます.
ソースコードを変更すると自動で更新されるのがいい感じです!

各メソッドが使えるかも試しておきましょう
curlでもいいですが, 直感的に使えるhttpieが便利です

# 全件取得(まだ0件)
$ http GET localhost:1323/posts

# 新規作成(idは自動インクリメント)
$ http POST localhost:1323/posts text=hoge
$ http GET localhost:1323/posts

# id=1のtextを更新
$ http PUT localhost:1323/posts/1 text=fuga
$ http GET localhost:1323/posts/1

# id=1を削除
$ http DELETE localhost:1323/posts/1
$ http GET localhost:1323/posts

Tips

go getなどコマンドを打ちたいときは

$ docker ps

で実行中のコンテナIDを調べて,

$ docker exec -it {CONTAINER_ID} sh

でコンテナ内に入れます

References

https://github.com/labstack/echo
https://github.com/jinzhu/gorm
Golang(Echo) x docker-composeでホットリロード用いた開発

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

Dockerが本番環境使用に厳しい理由

Dockerはとてもシンプルで動作も軽いため開発/テスト/デモ環境などで使用している方も多いと思います。しかし本番環境ではどうでしょうか。
Webサーバーのようにいくつも稼働させて、何台かダウンしてもOKのような環境では有効だと思いますが、そのような用途ばかりではありませんよね。

Dockerをモノリシックな本番環境で利用できるか検証した際、気になった点をメモしましたので、一例としてご参考いただければと。

理由その1.MACアドレスが固定できない。

Dockerは非常にインターフェース周りで柔軟な構成が簡単に組めることが魅力ですが、まだまだ改善の余地があります。

Dockerはインターフェースが一つの時は以下のようにMACを指定できます。

docker run -itd --name hoge -p 8060:8080 --network=net1 --mac-address 00:00:00:00:00:31 --ip 172.19.0.6

しかしながら、2つ以上インターフェースがある場合、MACを指定できません。起動後、後から追加/変更する場合もMACの指定はできません。docker network connect コマンドオプションにはMACを指定するオプションがないためです。(ここではコマンドで説明しましたが、composeを使用しても同様だと思います。)

docker network connect --ip 172.20.0.6 net2

本番で仮想環境を利用する際、MACを固定することは意外に重要です。
例えばMACアドレスがNodeを識別する方法として利用されている場合、コンテナが昨日と違うMACアドレスで起動してしまうとインストールされているアプリケーションがライセンスされたノードで起動していないと判断して停止する場合もありえます。

よって、以下のような条件の環境ではDockerは本番に不向きと言えそうです。

  • インターフェースを複数利用する。
  • MACアドレスを利用している。

理由その2.仮想ネットワークルーティング機能が弱い。

皆さんご存知の通り、Dockerで -p コマンドを使ってポートフォワードを行うことができます。(dockerではpublishと呼ばれているようです)

これは内部的にはホストのiptablesを利用しています。そのためiptablesの機能的、パフォーマンス的限界がDockerのネットワーキングの限界になります。

以下、パフォーマンステストをした際、気になった点をまとめました。

 

  • パケットロスが見られる。

今回のテストにおいて、ポートフォワードされないパケットが見られました。こちらはテスト環境に依存するかもしれませんので、一例として「そういうことがあった」ぐらいに気に留めてもらえればと思います。ここでもこれ以上、詳しく触れません。

 

  • -pコマンドを利用してportをマップする機能は若干不安定。

まずは簡単に機能の説明を。
ご存知の通り、Dockerでは -p <ホストのポート>:<コンテナのポート>のように指定してpublishすることができます。

docker run -p 80:8080 nginx

上記の例ではホストの80ポート宛てのパケットはnginxが稼働しているコンテナの8080ポートにフォワードされます。

実はこの設定は-p 13000-15999:13000-15999のように範囲を指定して大量のポートをマッピングすることができます。

このポートのレンジが数百程度であればよいのですが、数千を超えてくるとDockerがメモリを食い尽くしてコマンドが失敗します
(簡単に再現しますので、お手持ちのDockerで是非試してみてください。メモリ無くなりますが。。。)

理由は以下のような点が挙げられます。

  1. iptablesへ1ポートづつマッピングを追加している
  2. 1ポートのマッピングにつき、一定量のメモリを確保するプロセスが起動する

 
よって、メディアサーバー、UC、TURN、P2Pなど大量のポートをサービスに使用する場合、ではDockerは現在の所、不向きと言えるかもしれません。

回避策としては以下のようなものがあります。

回避策1.メモリを食い尽くす挙動を止める。
回避策2.大量のポートをマップする場合はpublish機能は使わない。host networkを使う。

回避策1はStackOverflowなどで有志が設定いじって回避しようと頑張っていますが、やり方によって副作用があるかもしれませんのでお勧めしません。

回避策2については、私の師でもあるDocker Captain、Bret Fisherに訊いたところ、このように使うなと言われました。
ホスト<->複数コンテナでの柔軟なポートマッピングがそもそもしたいんですけど。。。

コミュニティに対してはネットワーク周りの改善してくれと今後も言っていく予定です。

お手軽な仮想スイッチやルーターの機能があればいいな~。

 
何かフィードバックありましたら是非よろしくお願いします。
今後も気になった点はアップデートしていく予定です。

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

Docker/Kubernetes関連のセキュリティツール調査

Docker Bench for Security

v.1.3.5 (2019/11/05)
Apache License 2.0

Docker社公式のチェックツール
Dockerホストで実行して、Dockerホストの構成と稼働中のコンテナなどを検査

GitHub

Docker Security Scanningについて
Docker 公式のセキュリティ診断ツール「Docker Bench for Security」を試した

Trivy

v0.4.0 (2019/12/27)
GNU Affero General Public License v3.0

GitHub

フロントエンドでもTrivyを使って脆弱性対策したい!
Trivyをやっと試してみた!
Docker イメージの脆弱性検査ができる「Trivy」を使ってみた
CIで使えるコンテナの脆弱性スキャナ
気軽に使えるContainerの脆弱性スキャンツール Trivy を試してみた

Dockle

v0.2.4 (2019/12/05)
GNU Affero General Public License v3.0

コンテナイメージのセキュリティ診断ツール
プライベートレジストリにも対応している

GitHub

CIで簡単につかえるコンテナのセキュリティ診断「Dockle」
人を震えさせるツール「Dockle」の仕組みを解説〜Dockerセキュリティの基礎知識も一緒に

Clair (クレア)

v2.1.2 (2019/12/10)
Apache License 2.0

CoreOS社(現在はRedHat社)開発のコンテナイメージ脆弱性スキャンツール

GitHub

セキュアなDockerイメージを支援するClair
Clairで、Dockerイメージの脆弱性スキャンを試す
clairでローカルのDockerイメージの脆弱性スキャン

Vuls (バルス)

v0.9.1 (2019/11/26)
GNU Affero General Public License v3.0

日本製の脆弱性スキャナー

公式サイト
GitHub
Dockerイメージ

あなたのサーバは本当に安全ですか?今もっともイケてる脆弱性検知ツールVulsを使ってみた
進化するVuls!稼働中のDockerコンテナの脆弱性を検知する
脆弱性診断ツールVulsをDockerで運用する
VulsをDockerで構築
サーバの脆弱性チェックできるVulsをdockerを使って試した
Vulsをdocker-composeで手っ取り早く使う
脆弱性スキャンツール vuls 〜cron定周期スキャン編〜
Vulsを使った脆弱性チェック運用 [環境構築編]【セキュリティ対策】

OWASP ZAP(オワスプ・ザップ)

v2.8.1 (2019/08/28)
Apache License 2.0

無料のセキュリティ診断用プロキシツール

GitHub

docker 版OWASP ZAPを試してみる
DockerでOWASP ZAPを使う
Jenkins と OWASP ZAP で自動診断
OWASP ZAP CLI 入門(インストール、起動方法、基本的なオプション)

MicroScanner

v0.0.1-beta (2018/01/15)

コンテナイメージの脆弱性スキャンツール

GitHub

無料で脆弱性検査!Dockerfileに4行追加で導入できるmicroscannerを試してみた

kube-hunter

v0.2.0 (2019/11/27)
Apache License 2.0

Kubernetes向けペネトレーションテストツール

GitHub

Kubernetes向けペネトレーションテストツール kube-hunter の紹介
【Kube-hunter】Dockerワンライナーで30項目のkubernetes環境脆弱性テストができるOSSを試してみた

kube-bench

v0.2.2 (2019/12/06)
Apache License 2.0

CIS Kubernetes Benchmarkで定義されているセキュリティの
ベストプラクティスに従っているかどうかのセキュリティ監査を
行うことができる

GitHub

kubeaudit

v0.7.0 (2019/10/03)
MIT License

Kubernetes環境で動いている Pod に対して
セキュリティ監査を行うことができる

GitHub

kubesec

0.9.2 (2018/08/11)
Apache License 2.0

kubernetesのsecret定義を暗号化

GitHub

kubesecを使ってkubernetesのsecret定義を暗号化する

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

Dockerイメージの脆弱性スキャンツール調査

Docker Bench for Security

v.1.3.5 (2019/11/05)
Apache License 2.0

Docker社公式のチェックツール
Dockerホストで実行して、Dockerホストの構成と稼働中のコンテナなどを検査

GitHub

Docker Security Scanningについて
Docker 公式のセキュリティ診断ツール「Docker Bench for Security」を試した

Trivy

v0.4.0 (2019/12/27)
GNU Affero General Public License v3.0

GitHub

Trivyをやっと試してみた!
Docker イメージの脆弱性検査ができる「Trivy」を使ってみた
CIで使えるコンテナの脆弱性スキャナ
気軽に使えるContainerの脆弱性スキャンツール Trivy を試してみた

Dockle

v0.2.4 (2019/12/05)
GNU Affero General Public License v3.0

コンテナイメージのセキュリティ診断ツール
プライベートレジストリにも対応している

GitHub

CIで簡単につかえるコンテナのセキュリティ診断「Dockle」
人を震えさせるツール「Dockle」の仕組みを解説〜Dockerセキュリティの基礎知識も一緒に

Clair (クレア)

v2.1.2 (2019/12/10)
Apache License 2.0

CoreOS社(現在はRedHat社)開発のコンテナイメージ脆弱性スキャンツール

GitHub

セキュアなDockerイメージを支援するClair
Clairで、Dockerイメージの脆弱性スキャンを試す
clairでローカルのDockerイメージの脆弱性スキャン

Vuls (バルス)

v0.9.1 (2019/11/26)
GNU Affero General Public License v3.0

日本製の脆弱性スキャナー

公式サイト
GitHub
Dockerイメージ

進化するVuls!稼働中のDockerコンテナの脆弱性を検知する
脆弱性診断ツールVulsをDockerで運用する
VulsをDockerで構築
サーバの脆弱性チェックできるVulsをdockerを使って試した
Vulsをdocker-composeで手っ取り早く使う
脆弱性スキャンツール vuls 〜cron定周期スキャン編〜
Vulsを使った脆弱性チェック運用 [環境構築編]【セキュリティ対策】

MicroScanner

v0.0.1-beta (2018/01/15)

aqua社が提供している、コンテナイメージの脆弱性スキャンツール

GitHub

無料で脆弱性検査!Dockerfileに4行追加で導入できるmicroscannerを試してみた

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

Docker 関連のセキュリティツール調査

Docker Bench for Security

v.1.3.5 (2019/11/05)
Apache License 2.0

Docker社公式のチェックツール
Dockerホストで実行して、Dockerホストの構成と稼働中のコンテナなどを検査

GitHub

Docker Security Scanningについて
Docker 公式のセキュリティ診断ツール「Docker Bench for Security」を試した

Trivy

v0.4.0 (2019/12/27)
GNU Affero General Public License v3.0

GitHub

フロントエンドでもTrivyを使って脆弱性対策したい!
Trivyをやっと試してみた!
Docker イメージの脆弱性検査ができる「Trivy」を使ってみた
CIで使えるコンテナの脆弱性スキャナ
気軽に使えるContainerの脆弱性スキャンツール Trivy を試してみた

Dockle

v0.2.4 (2019/12/05)
GNU Affero General Public License v3.0

コンテナイメージのセキュリティ診断ツール
プライベートレジストリにも対応している

GitHub

CIで簡単につかえるコンテナのセキュリティ診断「Dockle」
人を震えさせるツール「Dockle」の仕組みを解説〜Dockerセキュリティの基礎知識も一緒に

Clair (クレア)

v2.1.2 (2019/12/10)
Apache License 2.0

CoreOS社(現在はRedHat社)開発のコンテナイメージ脆弱性スキャンツール

GitHub

セキュアなDockerイメージを支援するClair
Clairで、Dockerイメージの脆弱性スキャンを試す
clairでローカルのDockerイメージの脆弱性スキャン

Vuls (バルス)

v0.9.1 (2019/11/26)
GNU Affero General Public License v3.0

日本製の脆弱性スキャナー

公式サイト
GitHub
Dockerイメージ

あなたのサーバは本当に安全ですか?今もっともイケてる脆弱性検知ツールVulsを使ってみた
進化するVuls!稼働中のDockerコンテナの脆弱性を検知する
脆弱性診断ツールVulsをDockerで運用する
VulsをDockerで構築
サーバの脆弱性チェックできるVulsをdockerを使って試した
Vulsをdocker-composeで手っ取り早く使う
脆弱性スキャンツール vuls 〜cron定周期スキャン編〜
Vulsを使った脆弱性チェック運用 [環境構築編]【セキュリティ対策】

OWASP ZAP(オワスプ・ザップ)

v2.8.1 (2019/08/28)
Apache License 2.0

無料のセキュリティ診断用プロキシツール

GitHub

docker 版OWASP ZAPを試してみる
DockerでOWASP ZAPを使う
Jenkins と OWASP ZAP で自動診断
OWASP ZAP CLI 入門(インストール、起動方法、基本的なオプション)

MicroScanner

v0.0.1-beta (2018/01/15)

aqua社が提供している、コンテナイメージの脆弱性スキャンツール

GitHub

無料で脆弱性検査!Dockerfileに4行追加で導入できるmicroscannerを試してみた

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

Dockerデーモンを再起動すると、起動中の変更済みコンテナの中身はリセットされるのか

ゼロからDocker imageを作成する場合、検索しても出てこなかったので、自分の備忘録のためにもまとめておく

確認したかったこと

コンテナ内で実装した追加機能をホスト側にマウントしていなかった場合に、デーモンの再起動をしたらコンテナは削除され、設定はリセットされてしまうのか

これだけ

実施したこと

  • Redmine ver.4.0.4のDokcer imageを作成する(設定ファイルのホストマウントなし)
  • バッチでガントチャートの折りたたみ表示を追加する
  • Dockerデーモンを再起動する
# systemctl restart docker

結果

コンテナは削除されず、停止された状態でデーモンが再起動する
そのため、コンテナの中で編集したことは削除されない

とりあえずで立てたコンテナがあるマシンメンテのナンスもこれで安心?

マシンの再起動をしても生きているかの確認をしたら、追記したい

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