20200810のdockerに関する記事は21件です。

LocustでWebサイトの性能測定をする(とりあえずDockerで動かしてみた編)

はじめに

Webサイトの性能測定といえばJMeterが定番な感じだが、そもそもなかなか起動させるまでの道のりが長くて学習コスト的にアレだったので、シナリオがPythonでお手軽に書けるという噂のLocustを使ってみた。

今回は、EC2でDockerでインストールしてとりあえず動かすところまで。
ちなみに、t2.microでは動作が不安定なので、t3.mediumくらいで起動すると良い感じであった。

Dockerのインストール

これはもう定番の手順だけど一応書いておく。

yumの最新化
$ sudo yum update -y
Dockerのインストール
$ sudo yum install -y docker
Dockerの開始
$ sudo service docker start
ec2-userをdockerグループに追加
$ sudo usermod -a -G docker ec2-user

ここで1回ログアウトして再ログイン(セッションを作り直さないと設定が反映されない)。

Dockerの起動確認
$ docker info

↓こんな感じで標準出力されればOK。ダメならDockerが起動してないとかなんとかといったメッセージが出る。

Client:
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
(以下略)
docker-composeインストールのためにユーザ変更
$ sudo -i
docker-composeを拾ってきてインストール(バージョンは適宜変更する)
# curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
パーミッション変更
# chmod +x /usr/local/bin/docker-compose
戻る
# exit

これでDockerの仕様準備完了!簡単!

Locustの動くコンテナを作る

以下のようにDockerfileを書こう。
Pythonを動く環境を作って、locustをインストールして、ローカルのlocustfile.pyをコピーして起動!
ファイルはlocustfile.py固定になってしまうので、適宜変更したらリロードして起動する。

Dockerfile
FROM python

RUN pip install locust

WORKDIR /locust
COPY ./locustfile.py .

CMD ["locust"]

これを、docker-compose.yml で設定してdocker-compose upする。

docker-compose.yml
version: '3'
services:
  locust:
    build: .
    ports:
      - "8089:8089"

だがちょっと待て。肝心のlocustfile.pyが無いと起動しない。
以下が起動のための最低セットだ。

locustfile.py
from locust import HttpUser, task, between

class QuickstartUser(HttpUser):
    wait_time = between(1, 1)

    @task
    def get_contents(self):
        self.client.get("/test-contents.html")

試験対象のホストにはtest-contents.htmlを置いておこう。

さて、これでdocker-compose upしたら、EC2に8089でHTTP接続する。

いざ、動かす!

HTTP接続すると、以下のように設定画面が出る。

キャプチャ4.png

接続ユーザ数と、ユーザ生成/秒と、ホスト名だ。
ホスト名の後ろに、locustfile.pyを付けてアクセスするイメージだ。

適当に値を入れて起動すると、

キャプチャ5.png

といった感じで負荷状況が表示される。

さらに、Chartsを選択すると、

キャプチャ6.png

グラフも見られるぞ!

「Download Data」からこのグラフのネタが取れるかと思いきや、取れたcsvにはこの情報は含まれていなかった。なぜ……。

ということで、まずは性能測定の足掛かりができた!

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

Go言語アプリのDockerイメージをscratchで軽量化してみた

こんばんは、ねじねじおです。

Go言語で書いたアプリの Docker イメージを軽量化するには、マルチステージビルドを使って scratch をベースに構築するのがよいと聞いて、やってみました。

準備

まず、サンプルとして小さな Web API を echo で作ります。

$ mkdir app
$ cd app
$ go mod init example.com/example
$ go get github.com/labstack/echo/v4

下記のディレクトリ構成で server.go と Dockerfie を追加します。

-example
 |-app
    │-Dockerfile
    │-go.mod
    │-go.sum
    |-server.go
server.go
package main

import (
    "net/http"
    "time"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    // Echo instance
    e := echo.New()

    // Middleware
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    // Routes
    e.GET("/", func (c echo.Context) error {
        return c.JSON(http.StatusOK, []string{
            "Hello, World!",
            time.Now().Format(time.RFC3339),
        })
    })

    // Start server
    e.Logger.Fatal(e.Start(":1323"))
}
Dockerfile
FROM golang:1.14.7
WORKDIR /go/src/app

COPY ./ ./
RUN go mod download
RUN go build -o ./server ./server.go

ビルドして実行してみます。

$ docker build ./ -t example
$ docker run -e TZ=Asia/Tokyo -p 1323:1323 example ./server

動作確認。

$ curl http://localhost:1323/
["Hello, World!","2020-08-10T19:51:15+09:00"]

成功!!

では、イメージサイズを確認してみます。

$ docker images example
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
example             latest              5ef805ca57ec        2 minutes ago       908MB

908MB って、でかいのかな?
基準がわからないので、レイヤーを確認します。

$ docker history example
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
5ef805ca57ec        2 minutes ago       /bin/sh -c go build -o ./server ./server.go     20.5MB              
13249ee42cff        2 minutes ago       /bin/sh -c go mod download                      77.3MB              
a3e0d3e82f45        3 minutes ago       /bin/sh -c #(nop) COPY dir:cccd1ec30e0093efe…   4.96kB              
aa1a8385bb42        44 hours ago        /bin/sh -c #(nop) WORKDIR /go/src/app           0B                  
baaca3151cdb        3 days ago          /bin/sh -c #(nop) WORKDIR /go                   0B    
... 省略 ...

マルチステージビルドを使うと、go mod download と go build の領域を節約できそうです。

マルチステージビルドを使う

Dockerfileを変更します。
builderステージでコンパイル、できたバイナリファイルをコピーしてproductionステージを作ります。

FROM golang:1.14.7 AS base
WORKDIR /go/src/app

FROM base AS builder
COPY ./ ./
RUN go mod download
RUN go build -o ./server ./server.go

FROM base AS production
COPY --from=builder  /go/src/app/server ./

ビルドします。

$ docker build ./ -t example

イメージのサイズとレイヤーを確認。

$ docker images example
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
example             latest              62b3a8a02af3        3 minutes ago       822MB

$ docker history example
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
62b3a8a02af3        3 minutes ago       /bin/sh -c #(nop) COPY file:3d74d9674cd3943c…   12.2MB              
aa1a8385bb42        44 hours ago        /bin/sh -c #(nop) WORKDIR /go/src/app           0B                  
baaca3151cdb        3 days ago          /bin/sh -c #(nop) WORKDIR /go                   0B                  
... 省略 ...

イメージサイズは、822MB。少し小さくなりましたね。

動作確認です。

$ docker run -e TZ=Asia/Tokyo -p 1323:1323 example ./server
$ curl http://localhost:1323/
["Hello, World!","2020-08-10T19:58:28+09:00"]

成功!

しかし、先ほどの docker history の出力をみると、バイナリをCOPYしてくるレイヤーは、たかだか 12.2MB 。
対して、イメージ全体のサイズは、822MB。
ベースのイメージが大きいのですね。

scratch をベースに最終イメージを構築する

Goの実行環境にはGoは不要なので、ミニマムに scratch をベースに最終イメージを構築してみます。

失敗 その1

Dockerfile
FROM golang:1.14.7 AS base
WORKDIR /go/src/app

FROM base AS builder
COPY ./ ./
RUN go mod download
RUN go build -o ./server ./server.go

FROM scratch AS production
WORKDIR /go/bin
COPY --from=builder /go/src/app/server ./

ビルドします。

$ docker build ./ -t example

イメージのサイズとレイヤーを確認。

$ docker images example
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
example             latest              e1ba3f7f81f0        About a minute ago   12.2MB

$ docker history example
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
e1ba3f7f81f0        2 minutes ago       /bin/sh -c #(nop) COPY file:3d74d9674cd3943c…   12.2MB              
06d1e3bea55e        12 minutes ago      /bin/sh -c #(nop) WORKDIR /go/bin               0B    

イメージサイズは、 12.2MB 。
劇的に小さくなりました!!

動作確認です。

$ docker run -e TZ=Asia/Tokyo -p 1323:1323 example ./server
standard_init_linux.go:211: exec user process caused "no such file or directory"

エラーが発生して、起動できない。
いろいろ調べて見ると、builder と production で実行環境が異なるので、コンパイル時に CGO を無効にする必要がありました。

失敗 その2

コンパイル時に CGO を無効にするように変更して再チャレンジです。

Dockerfile
FROM golang:1.14.7 AS base
WORKDIR /go/src/app

FROM base AS builder
COPY ./ ./
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./server ./server.go

FROM scratch AS production
WORKDIR /go/bin
COPY --from=builder /go/src/app/server ./

ビルドして実行します。

$ docker build ./ -t example
$ docker run -e TZ=Asia/Tokyo -p 1323:1323 example ./server

起動しました!
動作確認です。

$ curl http://localhost:1323/
["Hello, World!","2020-08-10T11:53:39Z"]

成功!
いや、否。
タイムゾーンが無視されている。。
タイムゾーンは、 アジアの都市、東京 です。"+09:00" です。

そして成功へ

こちらのサイトに答えが書いてありました。
Using local time in a Golang Docker container built from Scratch

今回は、builder ステージがから /usr/share/zoneinfo をコピーする方法を採用しました。

Dockerfile
FROM golang:1.14.7 AS base
WORKDIR /go/src/app

FROM base AS builder
COPY ./ ./
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./server ./server.go

FROM scratch AS production
WORKDIR /go/bin
COPY --from=builder /go/src/app/server ./
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

ビルドして実行します。

$ docker build ./ -t example
$ docker run -e TZ=Asia/Tokyo -p 1323:1323 example ./server

動作確認です。

$ curl http://localhost:1323/
["Hello, World!","2020-08-10T21:11:29+09:00"]

タイムゾーンが反映されています!

イメージのサイズを確認します。

$ docker images example
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
example             latest              e673e01668c6        14 minutes ago      13.3MB

$ docker history example
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
e673e01668c6        14 minutes ago      /bin/sh -c #(nop) COPY dir:b39c255c3688d7205…   1.21MB              
3865c579a2d0        25 minutes ago      /bin/sh -c #(nop) COPY file:bafd1cb7f8670973…   12.1MB              
06d1e3bea55e        34 minutes ago      /bin/sh -c #(nop) WORKDIR /go/bin               0B   

13.3 MB。

OK。
ねじねじおでした。

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

Dockerイメージを全部消す

Dockerイメージの削除

Dockerはこれから勉強なので色々入れていって、すぐにごちゃごちゃになると思うので、消し方を記録しておく。
とりあえず入れたのを全部消したい。

取得済みイメージの一覧表示

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
wordpress           latest              2da59c54a06a        3 days ago          543MB
nginx               latest              08393e824c32        5 days ago          132MB
mysql               5.7                 718a6da099d8        5 days ago          448MB

イメージを削除する前にコンテナを削除する必要があるので
動いているコンテナの確認

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                  NAMES
4b66ce372544        wordpress           "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes              0.0.0.0:8080->80/tcp   some-wordpress
9f748d50ab07        mysql:5.7           "docker-entrypoint.s…"   8 minutes ago       Up 8 minutes              3306/tcp, 33060/tcp    some-mysql
76819ac5972a        nginx               "/docker-entrypoint.…"   23 hours ago        Exited (0) 21 hours ago                          some-nginx

nginxのみSTATUS列のExited (0) 21 hours agoで、停止していることがわかる。nginxのコンテナのみ削除できる。

nginxCONTAINER IDを指定してコンテナを削除

$ docker rm 76819ac5972a
76819ac5972a

削除できていることを確認

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
4b66ce372544        wordpress           "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes        0.0.0.0:8080->80/tcp   some-wordpress
9f748d50ab07        mysql:5.7           "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       3306/tcp, 33060/tcp    some-mysql

nginxが無くなっているのが確認できた。

停止していないコンテナを削除してみる。

$ docker rm 9f748d50ab07
Error response from daemon: You cannot remove a running container 9f748d50ab078c4c3c63be83df6c7726f4ce8664d7c01478cf026c3812d12209. Stop the container before attempting removal or force remove

稼働中なので削除できないと怒られる。

無理やり止めていい状況であれば、無理やり止める。今回は全部消すのが目的なので無理やり止める。

$ docker kill 9f748d50ab07
9f748d50ab07
$ docker kill 4b66ce372544
4b66ce372544

確認

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS               NAMES
4b66ce372544        wordpress           "docker-entrypoint.s…"   8 minutes ago       Exited (137) 4 seconds ago                        some-wordpress
9f748d50ab07        mysql:5.7           "docker-entrypoint.s…"   12 minutes ago      Exited (137) 32 seconds ago                       some-mysql

STATUS列が2つとも止まった。

あらためて2つとも削除する。

$ docker rm 9f748d50ab07
9f748d50ab07
$ docker rm 4b66ce372544
4b66ce372544

確認

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

全部止まった

やっとイメージが消せるので消す

$ docker rmi 08393e824c32
Untagged: nginx:latest
Untagged: nginx@sha256:36b74457bccb56fbf8b05f79c85569501...
Deleted: sha256:08393e824c32d456ff69aec72c64d1ab63fecdad...
Deleted: sha256:16ea6e7b0ecc56682daf0e01d89ffe04aeb702f6...
Deleted: sha256:d1c30fbca15bed39f9d6a613d05885ab2de964ed...
Deleted: sha256:e860d6c3bb27d4d057f6c5412b92afa0ae15664f...
Deleted: sha256:0e6a092cd837c31fb9b85896c5849a2a02ba8913...
$ docker rmi 718a6da099d8
Untagged: mysql:5.7
Untagged: mysql@sha256:da58f943b94721d46e87d5de208dc0730...
Deleted: sha256:718a6da099d82183c064a964523c0deca80619cb...
Deleted: sha256:058d93ef2bfb943ba6a19d8b679c702be96e3433...
Deleted: sha256:7bca77783fcf15499a0386127dd7d5c679328a21...
Deleted: sha256:183d05512fa88dfa8c17abb9b6f09a79922d9e9e...
Deleted: sha256:165805124136fdee738ed19021a522bb53de75c2...
Deleted: sha256:904abdc2d0bea0edbb1a8171d1a1353fa6de2215...
Deleted: sha256:d26f7649f78cf789267fbbca8aeb234932e23010...
Deleted: sha256:7fcf7796e23ea5b42eb3bbd5bec160ba5f5f47ec...
Deleted: sha256:826130797a5760bcd2bb19a6c6d92b5f4860bbff...
Deleted: sha256:53e0181c63e41fb85bce681ec8aadfa323cd00f7...
Deleted: sha256:d6854b83e83d7eb48fb0ef778c58a8b839adb932...
$ docker rmi 2da59c54a06a
Untagged: wordpress:latest
Untagged: wordpress@sha256:8e0e83b3feee510eae7b7d68bac74...
Deleted: sha256:2da59c54a06a069eb6830f4d2f125840f9672e96...
Deleted: sha256:a0b975d5fd5ff77342aa6add51bc6cb819a1ca20...
Deleted: sha256:2cdc7837508703fe0d38179bfb46736ed5966f1b...
Deleted: sha256:6ba52464be861d5820d3993f1679fb1959825b73...
Deleted: sha256:c009eaa948f2fdeac83c727e23ecf54e3cea2255...
Deleted: sha256:c1dcd220a514e0a20c296ac98504ae1a060611d9...
Deleted: sha256:4ea2c0ce663f0f818e515817b07f4c9a8748fff6...
Deleted: sha256:87c45811775aae1757da1a94f55ecbbbdeba70d9...
Deleted: sha256:f6e183c191d75a55ea7b0695c32ba9bd4a6f2dae...
Deleted: sha256:ff09d507a3ca7496a332579227770965c6156064...
Deleted: sha256:ffa2c187679ddbeeda9b9d41725fa4916f2b07f2...
Deleted: sha256:eaae8b52ab6afc664a6584033bd8942c7a99911a...
Deleted: sha256:56a340d84f17f5b4e83bd02ffd40a3b1273912dc...
Deleted: sha256:f8899bfcfa880bd6caa5078c27b488a37f6abdce...
Deleted: sha256:08b50110935f318104dd652795f0b0a2c6d007b3...
Deleted: sha256:3bcc29238c6f1ce1602b88b2317fd7429228c311...
Deleted: sha256:e7854f919e1ba15b6ac0b0e70cd2cb1eac7ca4cd...
Deleted: sha256:45c01c7d544fd67d36753507065e5458be16dfcf...
Deleted: sha256:8e311722d5028e3cb61f5dea8786ed5fbc54a3e3...
Deleted: sha256:2f245d38723aa315787ea341d92c1abbcccc9cb6...
Deleted: sha256:d0f104dc0a1f9c744b65b23b3fd4d4d3236b4656...

確認

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

全部消えた
すっきり

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

【Docker】docker-composeコマンド早見表

コマンド できること
docker-compose build イメージを構築する
docker-compose up イメージの構築・コンテナの構築・起動
docker-compose start 既存のコンテナの起動
docker-compose run イメージの構築・コンテナの構築・起動・コンテナ内でのコマンドの実行
docker-compose exec コンテナ内でのコマンドの実行

イメージの構築

# 初回の構築
docker-compose build

# Dockerfileを更新後の構築
docker-compose build --no-cache

キャッシュ
キャッシュという一度ビルドすると作成される、2回目以降のビルド処理を速やかにしてくれる機能がある。
Dockerfile更新時には、キャッシュを用いてビルドされるの更新内容が反映されない可能性があるので、2回目以降はキャッシュを無効にする必要がある。

コンテナ起動

起動

# フォアグラウンドで起動
docker-compose up

# バックグラウンドで起動
docker-compose up -d

再起動(コンテナはそのまま、ソースコードの変更を反映)

# フォアグラウンドで起動していた場合
docker-compose up

# バックグラウンドで起動していた場合
docker-compose restart

再起動(コンテナの再構築、ソースコードの変更を反映)

# フォアグラウンドで起動
docker-compose up

# バックグラウンドで起動
docker-compose up -d

再起動(Dockerfileの変更を反映)

# フォアグラウンドで起動
docker-compose up --build

# バックグラウンドで起動
docker-compose up -d --build

後片付け

# 停止と削除(コンテナ・ネットワーク)
docker-compose down

# 停止と削除(コンテナ・ネットワーク・イメージ)
docker-compose down --rmi all

# 停止と削除(コンテナ・ネットワーク・ボリューム)
docker-compose down -v

コンテナ内での実行

# そのまま実行する
docker-compose run --rm bundle install

# コンテナ内のターミナルに入って実行する
docker-compose exec sh
>bundle install

参考記事

https://qiita.com/tegnike/items/bcdcee0320e11a928d46

https://qiita.com/okyk/items/a374ddb3f853d1688820

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

Docker-ComposeでMySQL8をセットアップする時に若干はまったこと

はじめに

Gitbucketの組み込みDBであるH2Databaseはたまに壊れる事があるとのことで、ちゃんと運用するにはMySQLかPostgreSQLサーバを建てた方がよいとのこと。
GitbucketもMySQLも公式Dockerイメージから構築しようとした時に、ややハマった部分と対応作を備忘録する。

結論

一端、これでうまいこといっているので、良しとする。

# Docker-Composeのバージョンが低いのは、Portainerがまだバージョン2までしか対応していないため。特に意味はない
version: '2'
services:
  #MySQLの設定
  mysql:
    image: mysql
    container_name: gitbucket_mysql
    ports:
      - 3306:3306
      - 33060:33060
    environment:
      MYSQL_ROOT_PASSWORD: your_password
      MYSQL_DATABASE: gitbucket
      MYSQL_USER: gitbucket
      MYSQL_PASSWORD: gitbucket
    volumes:
      - mysql:/var/lib/mysql
    # ポイント1 キャラクタセットの設定、ポイント2 認証プラグインの変更
    command: ["--character-set-server=utf8mb4",  "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]

  gitbucket:
    image: gitbucket/gitbucket
    container_name: gitbucket
    depends_on:
      - mysql
    ports:
      - 8080:8080
    environment:
      GITBUCKET_DB_URL: jdbc:mysql://gitbucket_mysql:3306/gitbucket?useUnicode=true&characterEncoding=utf8
      GITBUCKET_DB_USER: gitbucket
      GITBUCKET_DB_PASSWORD: gitbucket
    volumes:
     - gitbucket:/gitbucket
    # ポイント3 MySQLが立ち上がるのをちょっとだけ待つ
    command: ["sh", "-c", "sleep 10 && java -jar /opt/gitbucket.war"]

volumes:
  mysql:
    driver_opts:
      type: none
      device: /PATH/TO/MOUNT/DIR/mysql
      o: bind
  gitbucket:
    driver_opts:
      type: none
      device: /PATH/TO/MOUNT/DIR/gitbucket
      o: bind


ポイント1 MySQL キャラクタセットの指定

command: ["--character-set-server=utf8mb4",  "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]

別にはまったわけではないが、MySQLのサーバ側のキャラセットを設定ファイル(my.cnf)なしで変更したかったので、起動パラメータでUTF8に指定した。

ポイント2 MySQL 認証プラグインの変更

command: ["--character-set-server=utf8mb4",  "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"]

MySQL8以降、標準の認証方式がRSA認証になったようなので、旧式のパスワード認証に変更する。新式の認証方法はGitbucket側が対応していなければならないが、現段階でWikiを見る限りまだ未対応?の模様。(ただ、ブログを見る限りMySQL8対応をされているようだが)

ポイント3 Gitbucket起動時にウェイトタイム設ける

command: ["sh", "-c", "sleep 10 && java -jar /opt/gitbucket.war"]

これが、一番はまった。

MySQLの初回立ち上がり時、まだデータベースがないので起動後すぐには接続できない。Docker-Composeで立ち上げるとGitbucket起動後もまだMySQLが準備中の段階。そのため、Gitbucket側で接続エラーになってしまう。

MySQLのDockerHubのDescribeにも記載されているが、こういった場合はシェルなどで接続リトライをするようにしている。

ちょっとダサいのはやむを得ないが、接続リトライとか面倒なので、てっとり早くウェイトタイム10秒をいれた。(10秒もいらんかも)

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

rails6の環境をdockerとmysqlで構築(メモ)

はじめに

個人用のメモです。
業務でほとんどdocker使わないので、忘れてしまいそうなので。。。
また、パーフェクトRuby on Railsを参考にしています。

ファイル構成

/app
|--- docker-compose.yml
|--- Dockerfile
|--- Gemfile
|--- Gemfile.lock
|--- .env

Rails用のイメージを作成

ファイル

Dockerfile
FROM ruby:2.7.1

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
    && apt-get update \
    && apt-get install -y build-essential nodejs yarn

RUN gem install bundler
WORKDIR /app
RUN bundle config set path vendor/bundle

CMD ["bash"]

コマンド(コンテナが作れるか確認)

$ docker build .
$ docker images
$ docker volume create app_bundle
$ docker volume create app_node_modules
$ docker colume ls
$ docker run -it -v <現在のディレクトリの絶対パス>:/app \
  -v app_bundle:/app/vendor/bundle \
  -v app_node_modules:/app/node_modules \
  -p 3000:3000 <IMAGE ID>

### コンテナの中 ###
# bundle install
# bundle exec rails new . --force --webpack=vue --skip-turbolinks --skip-test -d mysql
# bin/rails webpacker:install
# bin/rails s -b 0.0.0.0
# エラーになるが繋がったのを確認

コンテナが作れるの確認して作成したコンテナとイメージを削除し、新しくイメージを作成しました。
DockerfileDockerfile.devに変更しています。

docker-composeの作成

ファイル

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

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - '3000:3000'
    volumes:
      - .:/app
      - app_bundle:/app/vendor/bundle
      - app_node_modules:/app/node_modules
    tty: true
    stdin_open: true

volumes:
  app_bundle:
    driver: local
  app_node_modules:
    driver: local
.env
COMPOSE_FILE=<docker-compose.dev.ymlのファイルのパス>
Gemfile
### bundle initで作成 railsのバージョンのみ変更###

# frozen_string_literal: true

source "https://rubygems.org"

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

gem 'rails', '~> 6'

コマンド

$ docker-compose up -d
$ docker-compose ps
$ docker-compose exec web bash

### コンテナ内 ###
# bundle
# bundle exec rails new . --force --webpack=vue --skip-turbolinks --skip-test -d mysql
# bin/rails s -b 0.0.0.0

Mysql用のコンテナ作成

docker-compose.ymlに追記。

ファイル

docker-compose.yml
version: '3'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    environment:
      MYSQL_USERNAME: app_dev_user
      MYSQL_PASSWORD: password
      MYSQL_HOST: mysql
    ports:
      - '3000:3000'
    volumes:
      - .:/app
      - app_bundle:/app/vendor/bundle
      - app_node_modules:/app/node_modules
    tty: true
    stdin_open: true
    depends_on:
      - mysql

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - 3306:3306
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  app_bundle:
    driver: local
  app_node_modules:
    driver: local
  mysql-data:
    driver: local

コマンド

$ docker-compose up -d mysql
$ docker-compose exec mysql mysql -u root -p

### コンテナ内(mysql) ###
mysql> create user app_dev_user@"%" identified by 'password';
mysql> grant all on app_development.* to app_dev_user@"%";
mysql> grant all on app_test.* to app_dev_user@"%";

RailsとMysqlを繋ぐ

database.ymlの修正

database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME") { app_dev_user } %>
  password: <%= ENV.fetch("MYSQL_PASSWORD") { password } %>
  host: <%= ENV.fetch("MYSQL_HOST") { mysql } %>

DBの作成

$ docker-compose exec web bash

### コンテナ内(Rails) ###
# bin/rails db:create
# bin/rails s -b 0.0.0.0

いつもの画面が出れば完成。

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

Raspberry Pi4をDocker環境にするため、AlpineLinuxをインストール

はじめに

RaspberryPi4(4GB)にDockerホストOSをインストールし、コンテナを実行できる環境を作成する。
Dockerを実行するなら、ベースOSは軽量でないとと考え、Alpine Linuxを選んだ。

作成環境

  • software
    Windows10 Home 1909
    Raspberry Pi Imager1.4

対象環境

  • Hardware
    RaspberrPi 4GB
  • software
    OS:Alpine Linux 3.12.0 aarch64

OSインストール

事前準備

Alpine Linuxのチュートリアルに従い、インストールを行う。
https://wiki.alpinelinux.org/wiki/Raspberry_Pi

OSイメージは以下のリンクから、「RASPBERRY PIのaarch64」をダウンロード
https://alpinelinux.org/downloads/

0.フォーマット

balenaEtcherでImageを書き込もうとしたけど出来なかったため、おとなしくチュートリアルに従い、SDのフォーマットを実施。
特別なツールは使わずに、Windows標準のフォーマットで実施。ファイルシステムは「FAT32」。

ラズベリーパイ財団が出している「Raspberry Pi Imager」を使ってみることに。
※Raspberry Pi Imagerは対応しているラズパイ用OSを選択したらインストールできるという優れもの
 選択肢になくても、ローカル上のイメージから選ぶこともできるため、今回はローカル上のイメージからインストールを実施した。
 https://www.raspberrypi.org/downloads/

Raspberry Pi ImagerからOperating Systemを「ERASE」にし、フォーマットを実行。(もちろんファイルシステムはFAT32となる)

1.インストール

Raspberry Pi ImagerからOperating Systemを「Use custom」にし、ダウンロードしてきた「alpine-rpi-3.12.0-aarch64.tar.gz」を選択し、書き込みを実行。
Raspberry Pi Imagerでは書き込みできなかったため、.tar.gzファイルを素直に7-zipで解凍しD&DでSDに書き込み。

2.起動

microSDをRaspberry Pi4に差し込み無事起動を確認。

3.初期設定

起動したら、"root"でログイン、PWは不要

初期設定のため、以下のコマンドを実行。

$ setup-alpine

キーボードとタイムゾーンは設定するが、他は基本的にデフォルト設定としたため、何も入力せずにEnter押下。

WiFi設定もできたため、SSID、PWを入力。
IPは個別にまだ振っていないため、DHCPとした。

設定項目の詳細は参考リンクを参照。

設定が終わったら、以下コマンドで設定を保存し再起動。

$ lbu commit -d

(4.ディスクレスモードからsysモードへ切り替え)

※この作業はお好みで。ディスクレスモードのほうが、ストレージへの負担が少なくメリットが多いかも。
以下の「Installation」「Post-installation」を実行してくだけ。
https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi
上記の設定の中で、追加したUserでSSHログインも可能になる。

結局sysモードは辞めて、ディスクレスモードで実行してます。

4.初期設定後のもろもろ設定

「4.ディスクレスモードからsysモードへ切り替え」をしなかった場合に設定する内容。

4.1.Userの追加

$ apk add sudo
$ adduser foo
$ adduser foo wheel
$ visudo #82行目"wheel ALL=(ALL) ALL"のコメントアウトを外す。 保存はEsc :x

以後の設定は追加したUserからSSHで操作可能になる。
(root権限ログインを有効にしたらできると思うけど、こっちのが方がおそらく簡単)

4.2.WiFi自動起動

rc-update add wpa_supplicant boot
/etc/init.d/wpa_supplicant start

4.3.固定IPアドレス化

"setup-alpine","setup-interfaces"でDHCPでなくIP設定をすると、うまくネットワークにつながらなかった。
"setup-interfaces"でDHCPでいいので接続した後に、interfacesで設定を行う。

/etc/network/interfaces
auto wlan0
iface wlan0 inet static
        hostname alpine
        address 192.168.0.199 #←設定するIPアドレス
        netmask 255.255.255.0
        gateway 192.168.0.1

Dockerインストール

以下でdockerのリポジトリが「community」であることを確認。
https://pkgs.alpinelinux.org/packages?name=docker&branch=edge&arch=aarch64

・communityを追加

/etc/apk/repositories
http://dl-cdn.alpinelinux.org/alpine/v3.12/main
#http://dl-cdn.alpinelinux.org/alpine/v3.12/community
#http://dl-cdn.alpinelinux.org/alpine/edge/main
http://dl-cdn.alpinelinux.org/alpine/edge/community #<-コメントアウトを外す
#http://dl-cdn.alpinelinux.org/alpine/edge/testing

・インストール

$ apk update
$ apk add docker

・Serviceの登録

$ rc-update add docker boot
$ service docker start

・Docker-composeのインストール

$ apk add docker-compose
$ apk add py-pip python3-dev libffi-dev openssl-dev gcc libc-dev make 
$ pip3 install docker-compose

忘れずにコミット

$ lbu commit -d

Docker起動確認

定番の「hello-world」を実行し確認する。

$ docker run hello-world

以下が出力されればOK。
imageをpullし実行ができている。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
256ab8fe8778: Pull complete
Digest: sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
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.
    (arm64v8)
 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/

さいごに

今回、初めてAlipneLinuxを触ってみましたが、導入方法などについてはwiki(参考リンク)が充実していて、だいぶ助かりました。

apkコマンドに慣れておらずaptと入力しエラーがでたり、コミットを忘れてリブートして設定が保存されてなかったり、トラブルは多々ありましたが、これからこういったルーティンには慣れていきます。

参考リンク

AlipneLinux設定項目
https://wiki.alpinelinux.org/wiki/Installation
AlpineLinux Dockerセットアップ
https://wiki.alpinelinux.org/wiki/Docker

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

Flaskでエラー OSError: [Errno 98] Address already in use

現象

Flaskアプリケーションを作成中、サーバーを起動したまま何度もモジュールを修正していると、標題のエラーが発生した。

エラーメッセージ

OSError: [Errno 98] Address already in use

メッセージのままだけど、「利用しようとしているアドレスはすでにほかで使ってるから今は使えないよ」ということらしい。
こういう場合はポートが埋まってるんだろうと当たりをつけてエラーメッセージを検索する。

検索した結果以下の記事がでヒットした。
https://qiita.com/ringCurrent/items/2413c795372baa7b479d

エラー番号が「48」と「98」で違うけど、おそらく環境差異なので気にせず解決方法を実行していく。

1.「lsof」コマンドのインストール
lsofコマンドで使用中のポートを確認するらしいが、使用しているdocker環境には入ってないみたい。

(base) root@e8cf64ce12e9:/home/continuumio# lsof -i :5000
bash: lsof: command not found

さくっとインストールする。(OSがubuntuなのでaptを使用)

(base) root@e8cf64ce12e9:/home/continuumio# apt install lsof
Reading package lists... Done

2.重複しているポートの確認
重複して利用しているポートを確認する。対象のポートはFlaskの起動時に指定しているのでコードを確認する。

main.py
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000, debug=True)

lsofコマンドでポート5000を使っているプロセスを確認
(-i オプションで対象を限定しないと大量に抽出されるため注意)

(base) root@e8cf64ce12e9:/home/continuumio# lsof -i :5000
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
python  881 root    4u  IPv4 237229      0t0  TCP *:5000 (LISTEN)
python  901 root    4u  IPv4 237229      0t0  TCP *:5000 (LISTEN)
python  901 root    5u  IPv4 237229      0t0  TCP *:5000 (LISTEN)

3.抽出された一覧から不要なプロセスを終了させる。

  • kill 終了コマンド。物騒な名前。
  • -9 強制終了
  • :xxxx ポート番号

詳細は「man コマンド」で確認

(base) root@e8cf64ce12e9:/home/continuumio# kill -9 901

以上

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

Docker × Laravel メールの送信処理をローカルで確認する

ウェブサーバー、アプリケーションサーバー、データベースサーバーが用意されていれば最低限Laravelを動作させることはできますが、実際に開発を進めてくるとメールを送信する処理を書くことが多くあります。

ローカルでのメール確認のためにメールサーバーを用意して、たくさんのメールアカウントを作って、メールを送信して、各メールアカウントでログインして確認...するのはとても非効率です。

そこでメール送信テストツールのMailHogというツールが公式のDockerイメージが提供されています。
こちらを利用すると実際にメールを送信することなく、メール内容をWeb UIで確認できます。

MailHog

開発者向けのメールテストツール

前提

最強のLaravel開発環境をDockerを使って構築する【新編集版】

当記事は上記の記事の補足になる記事です。

Laravel環境構築

$ git clone git@github.com:ucan-lab/docker-laravel.git
$ cd docker-laravel/infrastructure
$ make create-project

まずはサクッと環境構築します。

環境

  • PHP 7.4.6
  • Laravel 7.21.0

手順

infrastructure/docker-compose.yml を編集する

$ infrastructure
$ docker-compose down

docker-compose.ymlDockerfile を変更する場合は予めコンテナを破棄しておくと良いです。

docker-compose.yml
services:
  mail:
    image: mailhog/mailhog
    ports:
      - 8025:8025

mail サービスの設定を services 配下に追記します。
特にカスタマイズは必要ないので、公式のMailHogイメージをそのまま利用します。

$ docker-compose up -d

コンテナを作成して起動します。

$ docker-compose ps
        Name                       Command              State                 Ports              
-------------------------------------------------------------------------------------------------
docker-laravel_app_1    docker-php-entrypoint php-fpm   Up      9000/tcp                         
docker-laravel_db_1     docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp, 33060/tcp
docker-laravel_mail_1   MailHog                         Up      1025/tcp, 0.0.0.0:8025->8025/tcp 
docker-laravel_web_1    nginx -g daemon off;            Up      0.0.0.0:80->80/tcp 

mail のコンテナが起動していればokです。

backend/.env

.env
MAIL_HOST=mail
MAIL_PORT=1025
MAIL_FROM_ADDRESS=info@example.com

環境変数にMailHogの設定を追記します。
ホスト名には mail サービス名を設定、MailHogのSMTPは1025ポートがデフォルトで待ち受けています。
それと送信元アドレスの設定が必要です。

メール送信テスト

$ docker-compose exec app php artisan tinker
Mail::raw('test mail',function($message){$message->to('test@example.com')->subject('test');});

http://127.0.0.1:8025

ScreenShot 2020-08-10 2.04.49.png

ScreenShot 2020-08-10 2.04.53.png

参考

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

ubuntu18.04を初期セットアップする話

前置き

最近,Ubuntuが重くなってきました.これを機にWSL2のUbuntuに移行しようかなと思ったのですが,SSHでリモートアクセスするようなワークステーションの場合まだいいかなと思うこの頃です.

ということで,Ubuntuをクリーンインストールする際のこれだけやっておけばひとまず大丈夫かなリストをメモっておきます.

実行環境

  • OS: Ubuntu 18.04 LTS
  • GPU: RTX 2070

手順

  1. update & upgrade
  2. SSHの設定
  3. ファイアウォールの設定
  4. pyenvのインストール
  5. CUDA ToolKit & Nvidia Driverのインストール
  6. dockerのインストール

1. update & upgrade

おなじみですね.終わったら再起動してください.

sudo apt update
sudo apt upgrade -y

2. SSHの設定

手順1. OpenSSHを使うことにします.次のコマンドでインストールしてください.

sudo apt install openssh-server
ssh -V

手順2. 公開鍵暗号方式を使うので鍵の生成をしておきます.パスフレーズを聞かれますが何も入力しなくても生成できますのでお好みでどうぞ.このコマンドの結果,/home/USER/.ssh に,秘密鍵「id_rsa」と公開鍵「id_rsa.pub」が生成されます.

ssh-keygen -t rsa

手順3. クライアントマシンからサーバマシンであるUbuntuにSSHで接続するので,クライアントマシンに秘密鍵を,Ubuntuに公開鍵を置きます.Ubuntuの場合,デフォルトの設定ではauthorized_keysというファイルに公開鍵をまとめておくようです.

mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
chmod 600 authorized_keys # 所有者にだけ読み書きを許可

手順4. SSHの設定ファイルを変更します.

Port 4649                    # 接続ポートの設定
PermitRootLogin no           # rootログインを禁止
PasswordAuthentication no    # パスワードログイン禁止
PermitEmptyPassword no       # パスワード無しのログインを禁止

手順5. SSHを有効にします.

sudo systemctl start sshd

手順6. クライアントマシンからUbuntuにSSH接続できるか確認

ssh -p 4649 {$USER}@{ipアドレス} -i {秘密鍵ファイル:id_rsa}

3. ファイアウォールの設定

手順1. ufwをインストールします.

sudo apt install ufw

手順2. ufwでファイアウォールを設定します.このとき,SSHで接続するためのポートを開放しておきましう.

sudo ufw logging on # ログ取得を有効化
sudo ufw allow 80   # HTTP通信に使用するポート
sudo ufw allow 443  # HTTPS通信に使用するポート
sudo ufw allow 4649 # SSH接続に使用するポート
sudo ufw default deny # 許可したポート以外の通信を遮断

手順3. 最後にファイアウォールを有効にします.

sudo ufw enable
sudo systemctl start ufw

4. pyenvのインストール

次の手順を参考にして,実行してください.

5. CUDA ToolKit & Nvidia Driverのインストール

手順1. NVIDIA Driverとの衝突をさけるため,nouveauを無効化しておきます.まずは次の手順でインストールされているかを確認.

lsmod | grep -i nouveau

手順3. 表示されたらnouveauがインストールされているので,無効化してください.

sudo vi /etc/modprobe.d/blacklist-nouveau.conf

次の内容を書き込んでください.

##### nouveau
blacklist nouveau
options nouveau modeset=0

次のコマンドを実行し,再起動してください.

sudo update-initramfs -u

手順4. 公式リポジトリから対象のCUDA Toolkitをダウンロードします.おすすめは手順が少ないrunファイルです.公式サイトにある通り,実行してください.

6. dockerのインストール

手順1. aptコマンドでインストールすれば,完了です.

sudo apt install docker.io -y
sudo apt install docker-compose -y

手順2. sudoコマンドを利用しなくても,dockerコマンドが実行できるようにします.次のコマンドを実行した後ログアウトし,再度ログインしてください.

sudo groupadd docker # dockerグループの作成
sudo gpasswd -a $USER docker # 現行ユーザをdockerグループに所
sudo systemctl restart docker # dockerデーモンを再起動

手順3. hello worldをやってみます.

docker pull hello-world # docker imageのダウンロード
docker run hello-world

おわりに

これだけやっておけば,ひとまず安心して運用できるかと思います.参考にさせていただいたみなさま,ありがとうございました.

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

Windows10 Home環境でのDockerインストール

Windows10 Home環境では、Hyper-Vを利用できないため、Dockerを利用するのは、Windows Pro環境より少々面倒です。以下はWSL2を利用してDockerをWindows Home環境にインストールする手順を示します。

Windows Homeのアップグレード

WSL2を利用するには、Windows Homeがversion 2004, Build 19041以上である必要がありますので、そうではない場合は、Windows Updateを利用してアップグレードする必要があります。

以下の手順でWindows Homeのバージョンを確認できます。

  • Windowsロゴキー + R で「ファイル名を指定して実行」ダイアログを開く
  • 「名前」欄にwinverを入力し、「OK」ボタンを押す

Windows Homeのアップグレード手順は以下です。

  • 「スタート」ボタン→「設定」の順にクリックする
  • 表示された「設定」画面の 「更新とセキュリティ」をクリックする
  • バージョンアップできる場合は「Windowsの次のバージョンが利用可能になりました。…」のようなメッセージが表示されるので、「ダウンロードしてインストール」リンクをクリックして、後はインストーラーの指示のとおりに進めばよい

WSL2のインストール

  • Windowsロゴキー + S で「Windows検索ボックス」を表示
  • 検索欄「pw」を入力し、「Windows PowerShellアプリ」が表示されるので、「管理者として実行」をクリック
  • PowerShellのCLIに「dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart」を入力し、実行
  • wsl2-kernelの更新手順に従って、wsl2-kernelを更新する(この手順がないと、次の手順で「Error: 0x1bc」エラーが出ることがあります。また、BIOS レベルでのハードウェア仮想化をBIOS 設定で有効にする必要があります。メーカーによって設定方法が違いますので、メーカーのマニュアルに従って対応してください。)
  • PowerShellのCLIに「wsl --set-default-version 2」を入力し、実行

WSL2のインストール手順はマイクロソフトドキュメントにもあります。

Docker Desktop のインストール

  • Git for Windowsをダウンロードし、インストーラーの指示通り、Git for Windowsをインストールする(各インストール画面の選択はすべてデフォルト選択で問題ありません。Dockerのチュートリアル実施に必要となります。Dockerのチュートリアルを実施しない方はこの手順をスキップしてかまいません。)
  • Docker Desktop for Windowsをダウンロードし、こちらの手順に従い、Docker Desktopをインストールする
  • 初期化が完了すると、Docker Desktop は開始チュートリアルが起動されるので、その手順のとおり、Runの手順まで進む
  • ブラウザを立ち上げてアドレス欄に「localhost]を入力し、dockerの「Getting Started」ページが正しく表示されたら、OK
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KubernetesでDocker Registryを構築する。

前提

Dockerでコンテナを構築する場合、コンテナイメージを持っていない場合自動的にDocker Hub等からダウンロードする。
これはKubernetesでも同様で、動くワーカノード上でコンテナイメージを持っていなければ自動でダウンロードする。(デフォルト定義の場合)
なので、クローズ環境でKubernetesを動かしたい場合は事前にすべてのワーカノード上に動作させるコンテナイメージを事前にロードしておく必要がある。

docker load -i xxx.tar 

ワーカノードが1台とかそんな話であれば問題はないけど、Kubernetes構築する以上○台インストールはあり得る上、それぞれに○個のコンテナイメージロードとか面倒です。

というわけで、KubernetesにDocker Hub的なもの(正式名称:Registry)を立ててそこからアクセスさせようというのが今回の目的です。

環境

Ubuntu 18.04.4 LTS
Docker version 19.03.6, build 369ce74a3c
Kubernetes v1.18(Kubeadm v1.8で3台ノード構築済み)
Rook+Ceph v1.4 (永続ボリューム用)
Rook+Cephの構築については追々書きます。

Docker Registryについて

細かい話は公式に記載しているので、とりあえず置いておいて、DockerでDocker Registryを構築するだけなら次のコマンドで問題ありません。

docker run -d -p 5000:5000 -v /home/user0/registry:/var/lib/registry registry

これでdocker pull localhost:5000/httpd:latest のように使用することができる。
なお、コンテナにタグlocalhost:5000/xxxをつけておく必要がある。
202008101202.jpg

しかし、これはlocalhostで接続する場合の話。
ドメイン(またはIPアドレス)で指定する場合、docker pull 192.168.200.5:5000/httpd:latestのように指定すれば解決かと思いきや、必ずHTTPS通信をするのでregistryコンテナに証明書を設定し起動する必要がある。
もし、registryコンテナ側に証明書の設定がないと次のようにエラーとなる。
202008101143.jpg

マニュアルに証明書の設定方法が記載されているのでそれを参照に設定したところで、適当な証明書では通信してくれない。
202008101155.jpg

めんどくさいことに、自己署名の証明書を入れてもダメ。
202008101156.jpg
ちゃんとした証明書があれば次の章は解決しますが、試験環境など正規な証明書が準備できない場合は次の通り証明書を作成します。

Docker用の証明書を作る

 解決法としてはルート証明書をクライアント(Dockerのホスト側)にインストールし、ルート証明書で署名されたサーバ証明書をサーバ(registryコンテナ側)にインストールする方法をとります。
 ここではドメインの証明書なので、hostsファイルか(ローカルの)DNSでドメイン名が解決できるようにしておきます。

ルート証明書を作る

 ルート証明書の作り方はよく出てるのでコマンドだけ。なお、チャレンジパスワードは空欄でないとエラーになります。

openssl genrsa 2048 > ca.key
openssl req -new -key ca.key  > ca.csr
openssl x509 -days 365 -req -signkey ca.key < ca.csr > ca.crt

サーバ証明書を作る

 サーバ証明書を作る前に、opensslの作業ファイル等を作ります。

mkdir demoCA
cd demoCA
mkdir private crl certs newcerts 
echo "01" > serial
touch index.txt
cd ../

 それで、サーバ証明書を作成しルート証明書で署名します。
 この時、サーバ証明書とルート証明書の項目に不一致があるとエラーが発生する項目があります。

openssl genrsa 2048 > server.key
openssl req -new -key server.key  > server.csr
openssl ca -days 365 -cert ca.crt -keyfile ca.key -in server.csr > server.crt

ルート証明書をDockerのホストに追加する

 この項目は、OSによって違うのでUbuntuの場合のみ記載します。
 ルート証明書を指定のディレクトリにコピーし、/etc/ca-certificates.confファイルに相対パスで追記します。(この場合はca.crtと追記)
 最後に再読み込みして完了です。

sudo cp ca.crt /usr/share/ca-certificates
sudo nano /etc/ca-certificates.conf 
sudo update-ca-certificates

KubernetesでDocker Registryを構築

 Kubernetesで構築する場合の説明。

事前準備

 ・すべてのワーカノードのDockerにコンテナイメージ(registry)を入れておく
 ・前章の通りサーバ証明書とルート証明書を作る
 ・ルート証明書を全てのワーカノードに反映しておく

永続ボリュームの作成

 Registryのコンテナイメージの保存先(/var/lib/registry/)を作成します。
 Webサーバと同じ扱いで特にコンテナごとにPVを分ける必要性もないため、今回の永続ボリュームはrook+cephのファイルストレージで作成します。なお、NFSのPVでも支障はないと思います。

pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvcregistry
  labels:
    pvc: registry
spec:
  storageClassName: rook-ceph-fs
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

 保存したら、kubernetesに読み込ませます。
kubectl apply -f pvc.yaml

サービスの作成

 この後Pod(Deployment)を作ったところで、IPアドレスを固定させないとめんどくさいことになるのでサービスで半固定のIPアドレスを発行させます。
 サービスでは、LoadBalancer、NodePort、ClusterIPの3種類が選べると思います。Kubernetesクラスタ外部にregistryを公開するのであればLoadBalancer型でいいと思いますが、今回はクラスタ内部だけに使えるregistryとして公開します。(=ClusterIPとして構築)

services.yaml
apiVersion: v1
kind: Service
metadata:
  name: srvregistry
spec:
  ports:
  - name: http
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: registry
  type: ClusterIP

 保存したら、kubernetesに読み込ませます。
kubectl apply -f services.yaml
 
 次のコマンドでClusterIPを確認します。
kubectl get services

 Kubernetes内の全ノードでドメインがこのIPアドレスへ解決できるようにDNSまたはhostsファイルを設定します。

証明書の保存

 kubernetesのsecretにサーバ証明書を保存します。
 サーバ証明書ファイルが保存されているディレクトリで次のコマンドを実行します。
 kubectl create secret generic scregistry --from-file=server.crt --from-file=server.key
 

Deploymentの作成

 最後にregistryのコンテナを作成します。
 ポート番号が443になるように設定変更を行っています。

deplyment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: depregistry
  labels:
    dep: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: registry
  template:
    metadata:
      labels:
        app: registry
    spec:
      containers:
      - name: registry
        image: registry
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 443
        volumeMounts: 
        - name: vol
          mountPath: /var/lib/registry 
        - name: conf
          mountPath: /certs/
        env:
        - name: REGISTRY_HTTP_TLS_CERTIFICATE
          value: /certs/server.crt 
        - name: REGISTRY_HTTP_TLS_KEY
          value: /certs/server.key
        - name: REGISTRY_HTTP_ADDR
          value: 0.0.0.0:443
      volumes: 
      - name: vol
        persistentVolumeClaim: 
          claimName: pvcregistry
      - name: conf
        secret:
          secretName: scregistry

 保存したら、kubernetesに読み込ませます。
kubectl apply -f deployment.yaml

Registryを使ってみる

Dockerで使用する場合

 Dockerでpushやpullを使うときは、docker pull (ドメイン名):(ポート番号)/(コンテナ名)のように定義します。(ただしポート番号が443の場合はポート番号を省略できます)
 なお、pushをする場合は事前に(ドメイン名):(ポート番号)/(コンテナ名)というタグを定義する必要があります。

docker tag ubuntu www.example.co.jp/ubuntu
docker push www.example.co.jp/ubuntu
docker pull www.example.co.jp/ubuntu

202008101259.jpg

Kubernetesで使用する場合

 Kubernetesで使用する場合は、yamlファイル内のimage: を(ドメイン名):(ポート番号)/(コンテナ名)と定義します。
 前章のようにregistryを作成した場合(ドメイン名www.example.co.jp、ポート番号443)にPodを作る場合は次のようになります。

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  containers:
  - name: test
    image: www.example.co.jp/httpd:latest
    ports:
    - containerPort: 80

なお、registryを立ち上げた直後はコンテナイメージがないため、Deployment等でイメージ展開する前に前章の通りコマンドを実行し、registry上にイメージをpushしておく。

(参考)そもそもKubernetesのDeploymentとして構築しない場合

 Docker本体でHTTPS通信対応registryを起動させる場合は、以下のコマンドで実行する。または、以下のコマンドを参照し、docker-compose経由で起動する。

docker run -d  \
-p 443:443 \
-v /home/user0/registry:/var/lib/registry  \
-v /home/user0/certs:/certs/ \
-e REGISTRY_HTTP_TLS_CERTIFICATE:/certs/server.crt  \
-e REGISTRY_HTTP_TLS_KEY:/certs/server.key \
-e REGISTRY_HTTP_ADDR:0.0.0.0:443 \
registry

参考文献

レジストリ・サーバのデプロイ — Docker-docs-ja 17.06 ドキュメント
Sanwa Systems Tech Blog | OpenSSLコマンドでオレオレ証明書を作り、ルート認証局としてサーバー証明書を発行する

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

【docker】公式チュートリアル (getting-started)やってみる

はじめに

dockerを勉強中なのですが、公式チュートリアルやっていなかったなぁと思いやってみると学びがあったのでアウトプットも兼ねてメモしておこうと思います。公式チュートリアルを雑に和訳しつつ、補足も添えていきます。
当方windows環境なので説明がwindowsベースです。

前提

・dockerインストール済
・gitインストール済

チュートリアルを開始する

インストール済の状態からチュートリアルを開始する場合は、dockerのアイコンをクリックして、Learnをクリックするとチュートリアルが起動します。インストール前ならインストール完了時に自動でチュートリアルが開始されるはずです。
image.png

下記の画面が立ち上がるので、Startします。
image.png

clone

チュートリアル用のコードをcloneします

git clone https://github.com/docker/getting-started.git

Build

docker build -t docker101tutorial .

DokerfileからDockerイメージを作成する際はこのbuildコマンドを使用します。-t docker101tutorialはDockerイメージのタグ名を指定しています。tはtagの頭文字のようです。.Dockerfileがカレントディレクトリにあるということを表しています。
まとめると上記コマンドは、カレントディレクトリにあるDokerfileからdocker101tutorialというタグ名でDockerイメージを作成する、という意味になります。Dockerイメージは、アプリケーションの実行に必要なファイル群が格納されたディレクトリで、コンテナのもとになるものです。

Run

docker run -d -p 80:80 --name docker-tutorial docker101tutorial

runコマンドは、Dockerイメージからコンテナを生成し起動するために使用するコマンドで、生成と起動を同時に実行することができます。生成するコマンドdocker createと起動するコマンドdocker startもあり、createしてからstartすることはrunするのと同じ動作になります。
-dはdetachモードで起動することを指定しており、これを指定しておくとバックグラウンド起動できます。これを指定せずに起動するとターミナルに情報が出力されるようになります。
上記コマンドは、docker101tutorialというDockerイメージからdocker-tutorialという名前のコンテナを起動します。
このときdockerの起動に失敗した場合は、ホスト側のポートを8080に変更してみてください。

Getting Started

localhost:80にアクセスして下記画面が表示されれば、チュートリアル用のコンテナにアクセスできています。ここからはこのチュートリアルに沿って和訳していきながらやっていきます。
image.png

The command you just ran

コンテナを生成、起動した下記コマンドの説明をします。

docker run -d -p 80:80 docker/getting-started
  • -d : バックグラウンドモードでコンテナを生成/起動します
  • -p 80:80: ホスト側のポート80をコンテナ側のポート80にマッピングする
  • docker/getting-started: 使用するイメージ

このコマンドは下記のように省略して記載することができます。
docker run -dp 80:80 docker/getting-started

The Docker Dashboard

ここで一旦、Docker Dashboardについて説明しておきます。Dashboardを起動することで、コンテナログを確認したり、コンテナ内のshellを起動できたりできます。このほかにも、ブラウザで開いたり、再起動、削除できたりすることができ、いろいろな操作がUIで直感的に操作できます。

Dashboardにアクセスすると、下記のような画面が開き、コンテナがRUNNINGしていることが確認できます。「jolly_bouman」のところは、ランダムな名前になるので別の名前になっているはずです。
image.png

What is a container?

コンテナとは何か・・?簡単に言うと、ホストマシン上での、その他プロセスとは隔離されたマシン上のプロセスです。プロセスというのは、マシンで実行されているプログラムのことです。プロセスの隔離は、Linuxのnamespacesとcgroupsという機能を利用しています。

What is a container image?

コンテナイメージとは・・?イメージは実行環境で動くコンテナのもと(ひな形)です。コンテナイメージの正体は、アプリケーションの実行に必要なファイル群が格納されたディレクトリです。環境変数やデフォルトで実行するコマンド、その他メタデータが含まれています。

Our Application

このチュートリアルで実行するアプリケーションはNode.jsで動作するtodoアプリです。Node.jsになじみがなくても大丈夫です。
ここでは、todoアプリとして最低限動くものを用意します。下記の手順に沿ってアプリを起動し、動作を確認してください。

Getting our App

  1. ここからソースコードをダウンロードします。
  2. zipを解凍すると、package.jsonと2つのサブディレクトリ(srcとspec)があります。

Building the App's Container Image

アプリケーションをビルドするために、ここではDockerfileを使います。Dockerfileはテキストベースのスクリプトで、コンテナイメージを生成するための指示書のようなものです。
下記の手順にそってDockerイメージを作成しましょう。

1. package.jsonと同じ階層ディレクトリにDockerfileを作成し、下記を記載してください。dockerfileには拡張子は必要ありません。

FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

2. ターミナル開き、appディレクトリまで移動して下記コマンドを実行してください。

docker build -t getting-started .

Dockerfileから新規のコンテナイメージを生成する場合はこのコマンドを使用します。ターミナルを確認すると多数の"層"をダウンロードしていることがわかります。これはnode:12-alpieイメージをベースイメージとして使用したためで、マシン上にこのイメージがない場合はダウンロードする必要があるからです。
ダウンロードが完了すると、アプリケーション内にコピーしてyarnを使ってアプリケーション依存関係をインストールします。依存関係のインストールはRUN yarn install --productionのコマンドで実行され、package.jsonでdevDependenciesに記載されているもの以外をアプリケーション内にインストールします。devDependenciesに記載されているものは開発時に必要となるパッケージであり、製品版(--production)では必要ないので--productionを指定しています。
CMDはコンテナイメージからコンテナを起動したときにデフォルトで実行されるコマンドです。つまり、docker run XXXXを実行したときにnode src/index.jsのコマンドが実行されるということです。
docker buildコマンドの最後の.Dockerfileがカレントディレクトリにあるということを意味しています。

Starting an App Container

イメージの準備ができたのでdocker runコマンドを使用してアプリケーションを実行します。
1.イメージを指定してdocker runコマンドでコンテナを起動します

docker run -dp 3000:3000 getting-started

-dはコンテナをバックグラウンドで起動すること意味していて、-pによってホスト側のポート3000とコンテナ側のポート3000をマッピングしています。このポートマッピングがないとアプリケーションにアクセスすることができません。

2.http://localhost:3000にアクセスするとアプリケーションにアクセスできます。

3.アイテムが想定通り追加されることが確認できるはずです。完了マークをつけることができるのと、追加したアイテムを削除することもできます。

ここに少し変更を加えてコンテナの管理について学んでいきます。

Updating our App

下記の手順に沿ってアプリケーションを更新してください。

  1. src/static/js/app.jsの56行目を下記のように変更します。
    image.png

  2. アップデートしたバージョンのイメージをbuildしましょう。下記コマンドを実行します。
    docker build -t getting-started .

  3. 更新したコードを使った新しいコンテナを起動します。
    docke run -dp 3000:3000 getting-started

このコードを実行したとき、次のようなエラーが表示されたはずです。
docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
(bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 0.0.0.0:3000 failed: port is already allocated.

このエラーの原因は、古いコンテナがまだポート3000で起動したままになっているからです。ホスト側の一つのポートで占有できるプロセスは一つだけです。
これを解決するには、古いコンテナを削除すればよいです。

Replacing our Old Container

コンテナを削除するために、まず停止します。停止をしないと削除できません。
古いコンテナを削除する方法は2通りあるので好きなほうで削除してください。

Removing a container using the CLI

1. docker psコマンドでコンテナIDを取得します

docker ps

2.コンテナを停止するためにdocker stopを使います

# <the-container-id> のところはdocker ps で取得したコンテナIDと差し替えてください
docker stop <the-container-id>

3.停止したコンテナをdocker rmコマンドで削除します

docker rm <the-container-id>

下記コマンドを使用するとコンテナの停止と削除を1行のコマンドで実行することができます。
docker rm -f <the-container-id>

Removing a container using the Docker Dashboard

Docker dashboardを使うと、2クリックでコンテナを削除することができます。CLIを使う場合と比べて簡単で直感的にコンテナを削除することができます。
1. dashboardを開き、削除したいコンテナにマウスオーバーすると右側にアクションボタンが表示されます
2. ゴミ箱アイコンをクリックしてコンテナを削除します
image.png
3. コンテナがなくなったことを確認します

Starting our updated app container

1. 更新したアプリケーションを起動します

docker run -dp 3000:3000 getting-started

2. http://localhost:3000にアクセスして、テキストが更新されていることを確認してください
image.png

Recap(要約)

アプリケーションの更新をしましたが、下記2点気づいたと思います。
1. 初めに登録したアイテムがすべて消えています。これはtodoリストアプリとして良くないので、これについては後の章で触れます
2. 小さな変更にしては、アプリを更新するのにたくさんのステップが必要でした。rebuildして新規のコンテナ起動をいちいちしなくてもよい方法を後の章で見ていきます。

アイテムが保持される方法について触れる前に、イメージを共有する方法について簡単に見ていきましょう。

とりあえず、ここまで。
随時加筆していこうと思います。

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

Docker

Docker

CentOS7で実施

■Dockerインストール
wget -qO- https://get.docker.com/ | sh
rpm -q docker-ce

■dockerサービスの起動
systemctl start docker

■dockerサービスの有効化
systemctl enable docker

■user01をdockerグループに所属させ、docker管理コマンドを実行できるようにする
usermod -G docker user01

■user01でログイン

■DockerHubにあるイメージのサーチ
docker search centos

DockerレジストリからDockerイメージをダウンロードする

docker pull {イメージ名} : {タグ名}

例)
docker pull centos:latest
docker pull centos:centos6
docker pull ubuntu

ダウンロードしたDockerイメージの一覧を確認する
docker images

■ローカルのイメージコンテナ一覧表示
docker image ls

■DockerHubにあるイメージをDockerホストにダウンロード
docker image pull centos:7

■確認
docker image ls

■DockerHubにあるイメージubuntuのlatestタグの付いたイメージをダウンロード
docker image pull ubuntu:latest

■Dockerコンテナを作成・実行

書式
docker run [オプション][--name {コンテナ名}] {イメージ名}[:{タグ名}][コンテナで実行するコマンド][引数]

主なオプション
  -d : バックグラウンドで実行する(後述)。既定では、コンテナーをフォアグラウンドで実行するため、
Webサーバーやアプリケーションサーバーなど常時実行するコンテナーで指定。
  -i : コンテナーの標準入力を開く。/bin/bashなどでコンテナーを操作する際に指定する。
  -t : tty(端末デバイス)を確保する。/bin/bashなどでコンテナーを操作する際に指定。
  -p : {ホストのポート番号}:{コンテナーのポート番号}:Dockerサーバーのホストと
ポートマッピングを構成
例)
docker run -i -t centos
exit

docker run -i -t ubuntu
apt-get update

OSのバージョン確認
cat /etc/lsb-release

確認
docker ps

①Dockerコンテナ操作
ダウンロードしたDockerホストにあるcentosイメージからDockerコンテナを作成
docker container run centos:7 echo "hoge hoge"

■Dockerコンテナの一覧を取得する
docker ps [-a]
-a : 停止中のコンテナも表示されます。

②Dockerコンテナ操作 動作中のコンテナがないことを確認
docker container ls

③作成したコンテナが自動停止されていることを確認
docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e72f15246a5e centos:7 "echo 'hoge hoge'" 19 seconds ago Exited (0) 18 seconds ago adoring_driscoll

■Dockerコンテナの起動
docker start { コンテナ名 | コンテナID }

④docker container runコマンドを実施し、ダウンロードしたDockerホストにあるcentosイメージを使用してDockerコンテナを作成
-itオプションとbashコマンドを実施して、コンテナの作成と同時にシェルを起動し、コンテナ内のシェルを使い、コマンド実行できるようにする
docker container run -it centos:7 bash
[root@97f5cba069e6 /]#

ps -elf
exit

docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97f5cba069e6 centos:7 "bash" About a minute ago Exited (127) 12 seconds ago lucid_fermat
e72f15246a5e centos:7 "echo 'hoge hoge'" 11 minutes ago Exited (0) 11 minutes ago adoring_driscoll

■デタッチモードでDockerコンテナの起動
docker container run -d centos:7 ping -c 50 127.0.0.1
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b1803680bff centos:7 "ping -c 50 127.0.0.1" 20 seconds ago Up 19 seconds peaceful_dubinsky

■実行結果を確認 引数のCONTAINER IDは一部でよい
docker logs 2b1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.040 ms

■Dockerコンテナへの接続
docker attach {コンテナ名 | コンテナID }

■Dockerコンテナの端末からデタッチとアタッチ
①bashを起動したdockerコンテナに接続し、コンテナの端末に接続
docker container run -it centos:7 bash

②Dockerコンテナの端末からデタッチ
ctrl+p ctrl+q (ctrlキーは押したまま)

③デタッチしたDockerコンテナの端末にアタッチ
docker container attach 24e
[root@24e504ac64fc /]#

④exitでコンテナのシェルを終了。コンテナは自動停止される
[root@24e504ac64fc /]# exit
exit
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

■Dockerコンテナのプロセスのポートの割り当て

①Apacheを起動して、外部からApacheにアクセスできるようにする
まず、DockerHubにApacheのオフィシャルコンテナがあるか確認する

docker search httpd --filter="is-official=true"
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
httpd The Apache HTTP Server Project 2447 [OK]

②docker run コマンドを実行してhttpdイメージをもとにDockerコンテナを作成
なお、-dでデタッチモードで起動 また-Pでhttpdイメージ内のApacheのプロセスにホストOS側のポートを自動的に割り当てる

docker container run -d -P httpd

なお、docker container runコマンドでコンテナを作成するときに作成元に指定したイメージがローカルにない場合は、自動的にDockeHubからローカルにダウンロードされる

③docker image ls でhttpdイメージがダウンロードされていることを確認
[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest d131e0fa2585 8 hours ago 102MB
httpd latest d4a07e6ce470 3 weeks ago 132MB
centos 7 9f38484d220f 6 weeks ago 202MB

④docker container ls でhttpdイメージをもとにコンテナが作成されていることを確認
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b3c9252760b httpd "httpd-foreground" 4 minutes ago Up 4 minutes 0.0.0.0:32768->80/tcp determined_lamarr

⑤ブラウザからhttpdアクセス
http://192.168.0.10:32768/
ホスト側IPアドレス:192.168.0.10
ホスト側ポート番号:32768

■起動済みのコンテナで追加コマンドを実施

⑥ ②で起動したhttpdイメージから作成したコンテナに追加でbashのプロセスを起動
-itオプションもあわせて指定するとコンテナの端末にアタッチされ、起動したbashを使いコンテナ内でコマンドを実行できる

[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b3c9252760b httpd "httpd-foreground" 14 minutes ago Up 14 minutes 0.0.0.0:32768->80/tcp determined_lamarr
[user01@localhost ~]$ docker container exec -it 2b3 bash
root@2b3c9252760b:/usr/local/apache2#

⑦コンテナで実行されているプロセス確認 未確認
ps -elf

■Dockerコンテナの停止
docker stop { コンテナ名 | コンテナID }
確認
docker ps

⑧Dockerコンテナの停止
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b3c9252760b httpd "httpd-foreground" 18 minutes ago Up 18 minutes 0.0.0.0:32768->80/tcp determined_lamarr
[user01@localhost ~]$ docker container stop 2b3
2b3
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

■Dockerコンテナを削除する
docker rm {コンテナ名} | {コンテナID}

⑨Dockerコンテナの削除
docker container rm 2b3

■Dockerイメージを作成する
docker commit {コンテナ名} | {コンテナID} [{ユーザ名} /]{イメージ名}

■コンテナ内の設定とコンテナのイメージ化

①centos6.8イメージからベースとするコンテナを起動
docker container run -it centos:6.8 bash

②コンテナにApacheをインストール
yum install -y httpd
chkconfig httpd on
echo "This is a test page" > /var/www/html/test.html

③コンテナの端末から切断
ctrl + p → q

④いま起動しているコンテナとそのベースイメージを比較
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48a7436935a4 centos:6.8 "bash" 5 minutes ago Up 5 minutes vigilant_dijkstra
[user01@localhost ~]$ docker container diff 48a | grep test.html
A /var/www/html/test.html

⑤ローカルにあるイメージ一覧を確認
docker image ls

⑥先ほど起動してApacheをインストールされたコンテナからイメージを作成 イメージ名「dockerintro 01/httpd-image:1.0」
[user01@localhost ~]$ docker container commit 48a dockerintro01/httpd-image:1.0
sha256:deddd7cdd8c99458ae1bf0b2080f4f83fe2795524c9734cc1c88e50674505cef

⑦イメージが作成されたことを確認
[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerintro01/httpd-image 1.0 deddd7cdd8c9 About a minute ago 303MB

⑧作成したイメージからコンテナを作成。「-p8080:80」と指定してホストOSのポート8080をコンテナ内の80に割り当て
また「-d」でデタッチモードで起動後、httpdを起動するため「/sbin/init」プロセスを起動
[user01@localhost ~]$ docker container run -p 8080:80 -d dockerintro01/httpd-image:1.0 /sbin/init
4551899157a2d54a380e882e73353d4afb988e69a3cc3a6653e7a18b1a8dd179

⑨dockerコンテナの起動確認
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4551899157a2 dockerintro01/httpd-image:1.0 "/sbin/init" 41 seconds ago Up 39 seconds 0.0.0.0:8080->80/tcp determined_johnson
48a7436935a4 centos:6.8 "bash" 20 minutes ago Up 20 minutes vigilant_dijkstra

10ホストOS側でブラウザから動作確認
http://192.168.0.10:8080/

■docker image をDokerHubに保存

①DokerHubにログイン
docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: aerosnow
Password:
WARNING! Your password will be stored unencrypted in /home/user01/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

■dockerintro01/httpd-image をDokerHubに保存
②イメージの確認
[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerintro01/httpd-image 1.0 deddd7cdd8c9 39 minutes ago 303MB

③決まったフォーマットでタグを付ける 「docker tag イメージID DockerHubのユーザ名/任意の名前」
フォーマット docker tag local-image:tagname new-repo:tagname
④DokerHubにpush push時に指定するのはnew-repo:tagname

③、④の実施
[user01@localhost ~]$ docker tag deddd7cdd8c9 aerosnow/httpd:ver1
[user01@localhost ~]$ docker push aerosnow/httpd
The push refers to repository [docker.io/aerosnow/httpd]
b3894c1e1a9f: Pushed
ad337ac82f03: Pushed
ver1: digest: sha256:e6a3c9952dc8d71a26fcbb02206953a69357d0996cafa935537c633fc02e1158 size: 741

⑤下記サイトでRepositoriesを確認
https://cloud.docker.com/repository/list

■Dockerイメージを削除する
docker rmi {イメージ名} | {イメージID}

例) コミット(イメージ作成)する

⑥Dockerイメージの削除
・イメージ一覧
[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
aerosnow/httpd ver1 deddd7cdd8c9 About an hour ago 303MB
dockerintro01/httpd-image 1.0 deddd7cdd8c9 About an hour ago 303MB
ubuntu latest d131e0fa2585 10 hours ago 102MB
httpd latest d4a07e6ce470 3 weeks ago 132MB
centos 6.8 82f3b5f3c58f 6 weeks ago 195MB
centos 7 9f38484d220f 6 weeks ago 202MB

・Dockerコンテナ停止
docker stop コンテナID
[user01@localhost ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4551899157a2 dockerintro01/httpd-image:1.0 "/sbin/init" About an hour ago Up About an hour 0.0.0.0:8080->80/tcp determined_johnson
48a7436935a4 centos:6.8 "bash" About an hour ago Up About an hour vigilant_dijkstra
[user01@localhost ~]$ docker stop 4551899157a2
4551899157a2

・Dockerイメージ削除
[user01@localhost ~]$ docker rmi dockerintro01/httpd-image:1.0
Untagged: dockerintro01/httpd-image:1.0

[user01@localhost ~]$ docker rmi -f aerosnow/httpd:ver1
Untagged: aerosnow/httpd:ver1
Untagged: aerosnow/httpd@sha256:e6a3c9952dc8d71a26fcbb02206953a69357d0996cafa935537c633fc02e1158
Deleted: sha256:deddd7cdd8c99458ae1bf0b2080f4f83fe2795524c9734cc1c88e50674505cef

[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE

⑦再度 docker image のpullを実施
[user01@localhost ~]$ docker pull aerosnow/httpd:ver1
ver1: Pulling from aerosnow/httpd
7ce0cebb9dca: Already exists
da94caf679e5: Already exists
Digest: sha256:e6a3c9952dc8d71a26fcbb02206953a69357d0996cafa935537c633fc02e1158
Status: Downloaded newer image for aerosnow/httpd:ver1

[user01@localhost ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
aerosnow/httpd ver1 deddd7cdd8c9 About an hour ago 303MB

ubuntu で作業

apt-get install apache2
apt-get install php5
apt-get install libapache2-mod-php5

起動確認
/etc/init.d/apache2 restart

ctl+p, ctl+qでコンテナから抜ける。

docker ps -a
CONTAINER ID を確認

docker commitコマンドでubuntuというコンテナをhttpdという名前のイメージとして保存する。

docker commit CONTAINERID ubu-httpd

docker imagesコマンドで確認
docker images

■同一リポジトリにhttpdタグを付与して管理する場合には次のようにオプションを指定する。

docker commit ubuntu ubuntu:httpd
docker images

■イメージを削除する

docker rmiコマンドでイメージを削除する。起動中のコンテナで使用しているイメージは削除できない

docker rmi ubu-httpd

mkdir test-dockerfile

cd test-dockerfile/

vi Dockerfile

Use Linux Distribution CentOS6.8

FROM centos:6.8

LABEL maintainer="hoge@hoge.com"

Install Apache & deploy main html file

RUN yum -y install httpd && chkconfig httpd on && echo "This is a test page2 (from dockerfile)." > /var/www/html/test.html

EXPOSE 80

cp Dcokerfile /root

docker image build -t dockerintro1/httpd-image-dockerfile:1.0 .

docker image history dockerintro1/httpd-image-dockerfile:1.0

docker inspect history dockerintro1/httpd-image-dockerfile:1.0

docker container run -p 8081:80 -d dockerintoro1/httpd-image-dockerfile:1.0 /sbin/init

docker container ls

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

ダークウェブをChromeから覗く闇のワンライナー Welcome to Underground

ダークウェブ(.onionドメイン)にアクセスする場合、ブラウザはTorを使う必要がありますが、docker内でTorを建ててプロキシとして使えば、どのブラウザ、またはCURL、pythonスクリプト等でもアクセスできちゃいます。
ワンライナーはこちらです。

networksetup -setsocksfirewallproxy Wi-fi localhost 9150 && networksetup -setsocksfirewallproxystate Wi-fi on && cd $(mktemp -d) && echo -e "FROM alpine:3.12\nRUN apk add tor" > Dockerfile && docker build . -t torproxy && docker run -p 9150:9150 torproxy sh -c "chown -R root:root /etc/tor/;chown -R root:root /var/lib/tor/ && echo 'SocksPort 0.0.0.0:9150' >> /etc/tor/torrc.sample && tor -f /etc/tor/torrc.sample" && networksetup -setsocksfirewallproxystate Wi-fi off

それでは解説します。

networksetup -setsocksfirewallproxy Wi-fi localhost 9150 # Wi-fiを利用時にSOCKSプロキシlocalhost:9150を利用して接続する設定を登録。
networksetup -setsocksfirewallproxystate Wi-fi on # Wi-fiのSOCKSプロキシをONにする
cd $(mktemp -d) # Dockerfileを生成するので一時ディレクトリに退避
echo -e "FROM alpine:3.12\nRUN apk add tor" > Dockerfile # この行は一度のみ実行すれば以後必須ではない
docker build . -t torproxy # この行は一度のみ実行すれば以後必須ではない
docker run -p 9150:9150 torproxy sh -c "chown -R root:root /etc/tor/;chown -R root:root /var/lib/tor/ && echo 'SocksPort 0.0.0.0:9150' >> /etc/tor/torrc.sample && tor -f /etc/tor/torrc.sample"
# 必要な調整をchownとtorrc.sample追記で行い、torを実行します
networksetup -setsocksfirewallproxystate Wi-fi off # プロキシをOFFにする。フォアグラウンドで動いているDockerがターミナルから中断されると、次にこのコマンドに移り正常に戻る

注意点があります。先頭2つと末尾のnetworksetupコマンドはMacかつWifiでの利用を想定したコマンドです。既に登録がある場合は上書きしに行くのでご注意ください。その他OSは手動か別コマンドでSOCKSプロキシを設定しワンライナーは中間部だけお使いください。MacでWi-Fi以外の場合は置換が必要です。以下のコマンドで調査できます。

$ networksetup -listallnetworkservices # 私の環境にはありませんが、Ethernetが次に多そう
An asterisk (*) denotes that a network service is disabled.
Wi-Fi
Bluetooth PAN
Thunderbolt Bridge

ワンライナーを実行するとdocker runがフォアグラウンドで走り、手動で中断されるまで間にプロキシが稼働しています。ipinfo.ioで違うIPやlocationが表示され、check.torproject.orgでConratulationsが表示されれば成功です。
スクリーンショット 2020-08-04 8.46.44.png

それでは実際にダークウェブに潜むonionドメインのウェブサイトを見てみましょう。誰でも知っている以下のサービスは.onionドメインも運用してくれています。

その他のダークウェブに存在するサービスはWikipediaにまとまっていますが、本家TorブラウザはJavaScriptをデフォルトで無効にするなど、悪意のあるページに対して対策を凝らしてますので、Chromeで不用意に覗くのはバッドプラクティスといえそうです。
networksetupやPC全体のプロキシ設定無しで、CURLでのアクセスは以下になります。

bash
$ curl -sL --socks5-hostname localhost:9150 facebookcorewwwi.onion

pythonは以下です。当初requests.exceptions.InvalidSchema: Missing dependencies for SOCKS support.というエラーが出たので、pip install pysocksで直りました。

python
import requests
proxies = {'http':'socks5://127.0.0.1:9150','https':'socks5://127.0.0.1:9150'}
print(requests.get('http://ipinfo.io',proxies=proxies).json())
{'ip': '185.220.102.8', 'hostname': '185-220-102-8.torservers.net', 'city': 'Berlin', 'region': 'Berlin', 'country': 'DE', 'loc': '52.5244,13.4105', 'org': 'AS60729 Zwiebelfreunde e.V.', 'postal': '10178', 'timezone': 'Europe/Berlin', 'readme': 'https://ipinfo.io/missingauth'}

ご一読ありがとうございました。「Welcome to Underground」は2chでバズった痛いコピペです。

358 :世界遺産:2006/08/14(月) 15:48:55 ID:O2Q5Lui70
中学時代のパソコンの授業でインターネットを使った時
みんなが自分の好きな漫画や野球のページを見てる時に
自分だけこれみよがしに2chにつないでAAとかを周りに見せてたこと
しかも「このページって何?」って聞かれた時に「ヤバイ奴らの集会所みたいなもん」とか答えたこと
さらに友達に2chへの行きかたを教えるためにヤフーで2chって検索させて
でてきたリンクをクリックして2chのトップページが表示された瞬間に
そいつの耳元で「Welcome to Underground」ってささやいたこと

参考文献。ありがとうございました。

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

Docker × Laravel Vueをインストールしてログイン機能まで実装する

DockerでLaravel環境を構築する記事を書きましたが、
Vue以外にもReactを選択したり、フロント側はそもそもリポジトリを分けて開発する場合もあり前回の記事では紹介しきれていませんでした。

今回はLaravel環境を構築したあと、Vueのインストールまで試してみます。

Laravel UI とは

Laravelバージョン 5.8 までは、php artisan make:auth というコマンドが用意されていましたが、 Laravel 6.0 以降は Laravel UI パッケージに切り離されました。

前提

最強のLaravel開発環境をDockerを使って構築する【新編集版】

当記事は上記の記事の補足になる記事です。

Laravel環境構築

$ git clone git@github.com:ucan-lab/docker-laravel.git
$ cd docker-laravel/infrastructure
$ make create-project
$ make install-recommend-packages # 推奨パッケージなのでやらなくても良い

http://127.0.0.1

とりあえず、Laravelの環境を構築します。

環境

  • PHP: 7.4.6
  • Laravel: 7.24.0
  • Laravel UI: 2.1.0
  • Node: 14.2.0
  • npm: 6.14.4
  • yarn: 1.22.4
  • Vue: 2.6.11

補足: npm, yarn どちらを使うのか?

正直どちらでも構わないと思います。
ただ、どちらを使うかプロジェクトで統一されている必要はあるかと思います。

今回はnpm, yarnコマンドを併記する形で進めたいと思います。

Vue プリセットのインストール

公式の手順に沿って、実行します。
私のDocker環境の場合は下記の流れになります。

$ cd infrastructure
$ docker-compose exec app bash
$ composer require laravel/ui
$ php artisan ui vue --auth
$ exit

app コンテナを抜けて web コンテナに入ります。

$ docker-compose exec web ash
$ npm install # yarn
$ npm run dev # yarn dev

http://127.0.0.1

補足: スクリーンショット

ホーム画面

ScreenShot 2020-08-10 2.48.30.png

右上にLOGIN, REGISTERのメニューが追加されています。

登録画面

ScreenShot 2020-08-10 13.52.16.png

ログイン画面

ScreenShot 2020-08-10 13.52.50.png

ログイン後のホーム画面(ダッシュボード)

ScreenShot 2020-08-10 13.52.27.png

リセットパスワード画面

ScreenShot 2020-08-10 13.53.41.png

ScreenShot 2020-08-10 13.53.54.png

ScreenShot 2020-08-10 13.53.59.png

ScreenShot 2020-08-10 13.54.23.png

ScreenShot 2020-08-10 13.55.02.png

パスワードリセットのメールはMailHogで確認しています。

補足: webコンテナのNode.js

webコンテナ内にNode(npm, yarn)が入ってますが、コンテナ内でビルドするのは非常に時間がかかってしまうので実際の開発ではMacローカルにNodeを入れて実行させるのが良いです。

補足: Nodeバージョン固定化

特定のバージョンのNode.jsでしか動かして欲しくない場合、package.jsonenginesフィールドにNode.jsのバージョンを明記しておくとyarn installnpm installした時に警告を表示してくれます。

package.json
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "bootstrap": "^4.0.0",
        "cross-env": "^7.0",
        "jquery": "^3.2",
        "laravel-mix": "^5.0.1",
        "lodash": "^4.17.13",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.20.1",
        "sass-loader": "^8.0.0",
        "vue": "^2.5.17",
        "vue-template-compiler": "^2.6.10"
    },
    "engines": {
        "node": "14.2.0"
    }
}

補足: Nodeバージョン自動切り替え設定ファイル

.node-versionpackage.json と同じディレクトリに配置しておくと、nodenvが自動的にNodeのバージョンを切り替えてくれて便利です。

.node-version
14.2.0

参考

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

シンプルなRESTFull API を PHPでちゃちゃっと作りたい場合

how to use

composer の インストール

$ docker pull composer
$ alias composer='docker run --rm -it -v $PWD:/app composer'

slim4-api-skeleton のインストールと設定

$ composer create-project maurobonfietti/slim4-api-skeleton [my-api-name]
$ cd [my-api-name]
$ composer install

立ち上げと確認

$ docker-compose up -d --build
$ curl http://localhost:8081/

{"api":"slim4-api-skeleton","version":"0.22.0","timestamp":1596992058}

src/Controller/Home.php

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Helper\JsonResponse;
use Pimple\Psr11\Container;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

final class Home
{
    private const API_NAME = 'slim4-api-skeleton';

    private const API_VERSION = '0.22.0';

    private $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    public function getHelp(Request $request, Response $response): Response
    {
        $message = [
            'api' => self::API_NAME,
            'version' => self::API_VERSION,
            'timestamp' => time(),
        ];

        return JsonResponse::withJson($response, json_encode($message), 200);
    }

    public function getStatus(Request $request, Response $response): Response
    {
        $this->container->get('db');
        $status = [
            'status' => [
                'database' => 'OK',
            ],
            'api' => self::API_NAME,
            'version' => self::API_VERSION,
            'timestamp' => time(),
        ];

        return JsonResponse::withJson($response, json_encode($status), 200);
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】 Dockerfile と docker-compose を用いてコマンド1行で開発環境構築する方法

はじめに

Docker で開発環境が構築ができるようになりたかったので、それを学習した備忘録になります。

目標

Docker で開発環境が構築ができるようになること。
具体的には docker-compose を用いて、Apache + PHP + MySQL 環境を構築することです。

学習の順序

自分が学習していった順序は以下の通りです。

  1. docker image pull & docker container run
  2. Dockerfile
  3. docker-compose

できるようになること

  1. docker image pull & docker container run
    これができると自分の好きなようにカスタマイズした Docker Image をコマンド1行で作成できるようになります。

  2. Dockerfile
    これができると誰かが作成した Docker Image を使用してサービスを利用できるようになります。

  3. docker-compose
    これができると複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをコマンド1行で実行できるようになります。

説明すること

今回は 1. の docker image pull & docker container run などの docker コマンドについての説明は省略します。
これから Dockerfiledocker-compose の2つについて説明していきます。

Dockerfile を説明する前に

皆さんはこんな経験ありませんか?

『Docker を勉強して使えるようになったけど、毎回毎回 docker container run コマンド実行後、コンテナにログインして足りないモジュールを導入したり、必要なディレクトリやファイルを作成するのが大変だわ。。。どうにかならないかしら。。。』

それ、Dockerfile なら解決できます!

Dockerfile

Dockerfile とは自分の好きなようにカスタマイズした Docker Image を作成するためのファイルになります。

Docker を使用する際に docker container run コマンド実行後に docker exec -it [コンテナID] /bin/bash コマンドでコンテナにログインしたあとに、足りないモジュールのインストールやディレクトリ・ファイルの作成など、各種コマンドを実行することがあるかと思われます。

それをあらかじめ Dockerfile に記述することで、そのようなコマンドを起動時に自動で実行してくれるカスタマイズ版 Docker Image を作成することができます。

使い方

Dockerfile の配置されたディレクトリで docker build -t [イメージ名] . コマンドを実行するとローカル環境に Dockerfile の内容を元にローカル環境に Docker Image が作成されます。

メリット

Dockerfile ファイルを記述することで、

『この Docker Image を pull してから、docker container run コマンドを実行した際は、必ず毎回、そのコンテナにログインして、このコマンドとこのコマンドを実行して〜(省略)』

などの手順書が

『 Dockerfile があるディレクトリで docker build -t [イメージ名] . コマンドを実行する。』

の1行で済むようになります。

docker-compose を説明する前に

皆さんはこんな経験ありませんか?

『動かすコンテナが一つの場合はあまり気にならないけど コンテナが複数ある環境を構築する場合、それらのコンテナ同士の接続の設定とかを docker container run コマンドのオプションで指定したり、その手順書をいちいち記述するのが大変だわ。。。どうにかならないかしら。。。』

それ、docker-compose なら解決できます!

docker-compose

docker-compose とは複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。

複数のコンテナを起動させる場合、各コンテナを起動するために、それぞれ起動コマンドを実行する必要がありました。
また、コンテナを起動する際に、いろいろなオプションを利用していました。コマンドや手順が複雑になると、他の環境で使う/使ってもらう場合に、ミスが発生しやすくなります。
他の環境でも同じ構成(同じ Docker イメージ)で動かせるという Docker のメリットを生かすには、起動手順なども簡単であってほしいですよね。

docker-compose では、Docker Image の作成やコンテナ起動のオプションなどを含め、複数のコンテナの定義を yml ファイル(docker-compose.yml)に書き、それを利用してDockerビルドやコンテナ起動をすることができます。

使い方

docker-compose.yml の配置されたディレクトリで docker-compose up -d コマンドを実行するだけです。
docker-compose.yml に書かれている内容で以下のような処理を実行します。

  1. ローカル環境に Docker Image を Dockerfile の内容で作成する or docker pull する
  2. docker container run コマンドを実行する前の前処理を行う(環境変数の宣言など)
  3. docker container run コマンドにいろいろオプションをつけて実行する(ポートやボリュームの設定など)

メリット

docker-compose.yml ファイルを記述することで、

『まず、このディレクトリで docker build -t [イメージ名] . コマンド実行後に、これとこれのコマンドを実行して、docker container run [イメージA]docker container run [イメージB] を行って〜』

などの Docker 環境構築手順書が

『docker-compose.yml ファイルがあるディレクトリで docker-compose up -d コマンドを実行する。』

の1行で済むようになります。

さいごに

『今まで頑張って書いてきた構築手順書とは一体何だったんだろう?』とちょっと悲しくなりますが、どんどん便利な世の中になっていきますね。
やったね!!

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

【初心者向け】 Dockerfile と docker-compose を用いてコマンド1行で開発環境構築する方法(Apache + PHP + MySQL)

はじめに

Docker で開発環境が構築ができるようになりたかったので、それを学習した備忘録になります。

目標

Docker で開発環境が構築ができるようになること。
具体的には docker-compose を用いて、Apache + PHP + MySQL 環境を構築することです。

学習の順序

自分が学習していった順序は以下の通りです。

  1. docker image pull & docker container run
  2. Dockerfile
  3. docker-compose

できるようになること

  1. docker image pull & docker container run
    これができると自分の好きなようにカスタマイズした Docker Image をコマンド1行で作成できるようになります。

  2. Dockerfile
    これができると誰かが作成した Docker Image を使用してサービスを利用できるようになります。

  3. docker-compose
    これができると複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをコマンド1行で実行できるようになります。

説明すること

今回は 1. の docker image pull & docker container run などの docker コマンドについての説明は省略します。
これから Dockerfiledocker-compose の2つについて説明していきます。

先に作ったものの共有

ちょっと待ってください。。。。。

Dockerfile を説明する前に

皆さんはこんな経験ありませんか?

『Docker を勉強して使えるようになったけど、毎回毎回 docker container run コマンド実行後、コンテナにログインして足りないモジュールを導入したり、必要なディレクトリやファイルを作成するのが大変だわ。。。どうにかならないかしら。。。』

それ、Dockerfile なら解決できます!

Dockerfile

Dockerfile とは自分の好きなようにカスタマイズした Docker Image を作成するためのファイルになります。

Docker を使用する際に docker container run コマンド実行後に docker exec -it [コンテナID] /bin/bash コマンドでコンテナにログインしたあとに、足りないモジュールのインストールやディレクトリ・ファイルの作成など、各種コマンドを実行することがあるかと思われます。

それをあらかじめ Dockerfile に記述することで、そのようなコマンドを起動時に自動で実行してくれるカスタマイズ版 Docker Image を作成することができます。

使い方

Dockerfile の配置されたディレクトリで docker build -t [イメージ名] . コマンドを実行するとローカル環境に Dockerfile の内容を元にローカル環境に Docker Image が作成されます。

メリット

Dockerfile ファイルを記述することで、

『この Docker Image を pull してから、docker container run コマンドを実行した際は、必ず毎回、そのコンテナにログインして、このコマンドとこのコマンドを実行して〜(省略)』

などの手順書が

『 Dockerfile があるディレクトリで docker build -t [イメージ名] . コマンドを実行する。』

の1行で済むようになります。

docker-compose を説明する前に

皆さんはこんな経験ありませんか?

『動かすコンテナが一つの場合はあまり気にならないけど コンテナが複数ある環境を構築する場合、それらのコンテナ同士の接続の設定とかを docker container run コマンドのオプションで指定したり、その手順書をいちいち記述するのが大変だわ。。。どうにかならないかしら。。。』

それ、docker-compose なら解決できます!

docker-compose

docker-compose とは複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。

複数のコンテナを起動させる場合、各コンテナを起動するために、それぞれ起動コマンドを実行する必要がありました。
また、コンテナを起動する際に、いろいろなオプションを利用していました。コマンドや手順が複雑になると、他の環境で使う/使ってもらう場合に、ミスが発生しやすくなります。
他の環境でも同じ構成(同じ Docker イメージ)で動かせるという Docker のメリットを生かすには、起動手順なども簡単であってほしいですよね。

docker-compose では、Docker Image の作成やコンテナ起動のオプションなどを含め、複数のコンテナの定義を yml ファイル(docker-compose.yml)に書き、それを利用してDockerビルドやコンテナ起動をすることができます。

使い方

docker-compose.yml の配置されたディレクトリで docker-compose up -d コマンドを実行するだけです。
docker-compose.yml に書かれている内容で以下のような処理を実行します。

  1. ローカル環境に Docker Image を Dockerfile の内容で作成する or docker pull する
  2. docker container run コマンドを実行する前の前処理を行う(環境変数の宣言など)
  3. docker container run コマンドにいろいろオプションをつけて実行する(ポートやボリュームの設定など)

メリット

docker-compose.yml ファイルを記述することで、

『まず、このディレクトリで docker build -t [イメージ名] . コマンド実行後に、これとこれのコマンドを実行して、docker container run [イメージA]docker container run [イメージB] を行って〜』

などの Docker 環境構築手順書が

『docker-compose.yml ファイルがあるディレクトリで docker-compose up -d コマンドを実行する。』

の1行で済むようになります。

さいごに

『今まで頑張って書いてきた構築手順書とは一体何だったんだろう?』とちょっと悲しくなりますが、どんどん便利な世の中になっていきますね。
やったね!!

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

【初心者向け】Dockerfile と docker-compose を用いてコマンド1行で開発環境構築する方法

はじめに

Docker で開発環境が構築ができるようになりたかったので、それを学習した備忘録になります。

目標

Docker で開発環境が構築ができるようになること。
具体的には docker-compose を用いて、Apache + PHP + MySQL 環境を構築することです。

学習の順序

自分が学習していった順序は以下の通りです。

  1. docker image pull & docker container run
  2. Dockerfile
  3. docker-compose

できるようになること

  1. docker image pull & docker container run
    これができると自分の好きなようにカスタマイズした Docker Image をコマンド1行で作成できるようになります。

  2. Dockerfile
    これができると誰かが作成した Docker Image を使用してサービスを利用できるようになります。

  3. docker-compose
    これができると複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをコマンド1行で実行できるようになります。

説明すること

今回は 1. の docker image pull & docker container run などの docker コマンドについての説明は省略します。
これから Dockerfiledocker-compose の2つについて説明していきます。

Dockerfile を説明する前に

皆さんはこんな経験ありませんか?

『Docker を勉強して使えるようになったけど、毎回毎回 docker container run コマンド実行後、コンテナにログインして足りないモジュールを導入したり、必要なディレクトリやファイルを作成するのが大変だわ。。。どうにかならないかしら。。。』

それ、Dockerfile なら解決できます!

Dockerfile

Dockerfile とは自分の好きなようにカスタマイズした Docker Image を作成するためのファイルになります。

Docker を使用する際に docker container run コマンド実行後に docker exec -it [コンテナID] /bin/bash コマンドでコンテナにログインしたあとに、足りないモジュールのインストールやディレクトリ・ファイルの作成など、各種コマンドを実行することがあるかと思われます。

それをあらかじめ Dockerfile に記述することで、そのようなコマンドを起動時に自動で実行してくれるカスタマイズ版 Docker Image を作成することができます。

使い方

Dockerfile の配置されたディレクトリで docker build -t [イメージ名] . コマンドを実行するとローカル環境に Dockerfile の内容を元にローカル環境に Docker Image が作成されます。

メリット

Dockerfile ファイルを記述することで、

『この Docker Image を pull してから、docker container run コマンドを実行した際は、必ず毎回、そのコンテナにログインして、このコマンドとこのコマンドを実行して〜(省略)』

などの手順書が

『 Dockerfile があるディレクトリで docker build -t [イメージ名] . コマンドを実行する。』

の1行で済むようになります。

docker-compose を説明する前に

皆さんはこんな経験ありませんか?

『動かすコンテナが一つの場合はあまり気にならないけど コンテナが複数ある環境を構築する場合、それらのコンテナ同士の接続の設定とかを docker container run コマンドのオプションで指定したり、その手順書をいちいち記述するのが大変だわ。。。どうにかならないかしら。。。』

それ、docker-compose なら解決できます!

docker-compose

docker-compose とは複数のコンテナで構成されるアプリケーションについて、Docker Image のビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。

複数のコンテナを起動させる場合、各コンテナを起動するために、それぞれ起動コマンドを実行する必要がありました。
また、コンテナを起動する際に、いろいろなオプションを利用していました。コマンドや手順が複雑になると、他の環境で使う/使ってもらう場合に、ミスが発生しやすくなります。
他の環境でも同じ構成(同じ Docker イメージ)で動かせるという Docker のメリットを生かすには、起動手順なども簡単であってほしいですよね。

docker-compose では、Docker Image の作成やコンテナ起動のオプションなどを含め、複数のコンテナの定義を yml ファイル(docker-compose.yml)に書き、それを利用してDockerビルドやコンテナ起動をすることができます。

使い方

docker-compose.yml の配置されたディレクトリで docker-compose up -d コマンドを実行するだけです。
docker-compose.yml に書かれている内容で以下のような処理を実行します。

  1. ローカル環境に Docker Image を Dockerfile の内容で作成する or docker pull する
  2. docker container run コマンドを実行する前の前処理を行う(環境変数の宣言など)
  3. docker container run コマンドにいろいろオプションをつけて実行する(ポートやボリュームの設定など)

メリット

docker-compose.yml ファイルを記述することで、

『まず、このディレクトリで docker build -t [イメージ名] . コマンド実行後に、これとこれのコマンドを実行して、docker container run [イメージA]docker container run [イメージB] を行って〜』

などの Docker 環境構築手順書が

『docker-compose.yml ファイルがあるディレクトリで docker-compose up -d コマンドを実行する。』

の1行で済むようになります。

さいごに

『今まで頑張って書いてきた構築手順書とは一体何だったんだろう?』とちょっと悲しくなりますが、どんどん便利な世の中になっていきますね。
やったね!!

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

【Rails】ArgumentError: Malformed version number string 0.32+gitでwebpacker:installが実行できない場合の対処方法

はじめに

webpacker:installを実行すると表題のエラーメッセージが表示されてしまい、Railsが実行できない状況が起きました。
今回はこの現象の回避方法についてまとめます。

この記事の対象者

  • 表題のエラーメッセージが表示され、webpacker:installを実行できない人

実際にどのようなエラーになるのか

エラーに遭遇した環境

Docker公式のRuby:2.7.1を利用したコンテナで遭遇しました。
他の環境では試していないため、同じ方法で対処できると断定はできませんが、参考になればと思います。
使用したDockerfileとRailsのバージョンは以下の通りです。

Dockerfile
FROM ruby:2.7.1
LABEL maintainer="TomoProg"
RUN apt-get update -qq && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs \
    default-mysql-client \
    vim-tiny

RUN apt-get install -y yarn

RUN mkdir /myapp
WORKDIR /myapp
$ rails --version
Rails 6.0.3.2

実際のエラーメッセージ

webpacker:installを実行すると以下のようなエラーメッセージが表示されました。

root@3cd2b69c861a:/myapp# bin/rails webpacker:install
rails aborted!
ArgumentError: Malformed version number string 0.32+git
/usr/local/bundle/gems/webpacker-4.2.2/lib/tasks/webpacker/check_yarn.rake:12:in `block (2 levels) in <main>'
/usr/local/bundle/gems/railties-6.0.3.2/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/usr/local/bundle/gems/railties-6.0.3.2/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/usr/local/bundle/gems/railties-6.0.3.2/lib/rails/command.rb:48:in `invoke'
/usr/local/bundle/gems/railties-6.0.3.2/lib/rails/commands.rb:18:in `<main>'
/usr/local/bundle/gems/bootsnap-1.4.7/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/usr/local/bundle/gems/bootsnap-1.4.7/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.7/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/usr/local/bundle/gems/bootsnap-1.4.7/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.4.7/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/usr/local/bundle/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:324:in `block in require'
/usr/local/bundle/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:291:in `load_dependency'
/usr/local/bundle/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:324:in `require'
/myapp/bin/rails:9:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
/usr/local/bundle/gems/spring-2.1.0/bin/spring:49:in `<top (required)>'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'
/usr/local/bundle/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
/myapp/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => webpacker:install => webpacker:check_yarn
(See full trace by running task with --trace)

原因

webpacker:installする際にyarnが必要なのですが、
そのままapt-getでインストールすると0.32+gitというバージョンでインストールされてしまい、
webpack:installした際に行われるyarnのバージョンチェック時にエラーが出てしまうようです。
ちなみにyarnのバージョンは以下のコマンドで確認できます。

$ yarn --version
0.32+git

対処方法

yarnの公式サイトに掲載されているこちらのインストール方法を参考に、安定版で最新のyarnをインストールするようにDockerfileを下記のように変更しました。
(このインストール方法はUbuntu/Debianでのインストール方法です。別のOSの場合はリンク先のOperating Systemのプルダウンメニューから環境に合わせて確認してください。)

Dockerfile
FROM ruby:2.7.1

# -- 省略 --

# そのままapt-getでインストールする方法ではなく
#RUN apt-get install -y yarn

# 公式のインストール方法を参考に安定版で最新のyarnをインストールする
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
RUN apt-get update && apt-get install yarn

# -- 省略 --

その結果、yarnのバージョンが変わり、webpacker:installが正常に完了するようになりました。
実際のyarnのバージョンとwebpacker:installの実行結果は下記の通りです。

yarnのバージョン確認

$ yarn --version
1.22.4

webpacker:installの実行結果

root@cb295863c75e:/myapp# bin/rails webpacker:install
      create  config/webpacker.yml
Copying webpack core config
      create  config/webpack
      create  config/webpack/development.js
      create  config/webpack/environment.js
      create  config/webpack/production.js
      create  config/webpack/test.js
Copying postcss.config.js to app root directory
      create  postcss.config.js

-- 省略 --

├─ thunky@1.1.0
├─ type-is@1.6.18
├─ unpipe@1.0.0
├─ utils-merge@1.0.1
├─ wbuf@1.7.3
├─ webpack-dev-middleware@3.7.2
├─ webpack-dev-server@3.11.0
└─ ws@6.2.1
Done in 280.04s.
Webpacker successfully installed ? ?

まとめ

ArgumentError: Malformed version number string 0.32+gitが起きた際の対処方法をまとめてみました。
同じようなエラーで困っている方に参考になればと思います。

それでは良いRailsライフを!

TomoProg

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