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

[Go言語] Airを使って最短でホットリロードを実現する

環境 以下の実行環境で動作を確認しています。 $ go version go version go1.15.4 darwin/amd64 $ docker -v Docker version 20.10.10, build b485636 $ docker-compose -v docker-compose version 1.29.2, build 5becea4c ホットリロードのライブラリといえば色々ありますが・・・ 最近ではAirが1番流行っているようです。サクッと試してみます。 Star History 必要なファイルを作成する 以下のファイルが必要になります。 $ tree . ├── Dockerfile ├── air.toml ├── docker-compose.yml ├── go.mod └── server.go シンプルなAPIサーバーを作成する リクエストを行うと「Hello, World」とレスポンスをするシンプルなAPIサーバーを作成します。 server.go package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } Dockerfileを作成する Dockerfileを作成します。Golang - Official Image | Docker Hub に記述されているものに少し手を加えています。 Dockerfile FROM golang:1.17 WORKDIR /go/src/app COPY . . RUN go get -d -v ./... RUN go install -v ./... RUN go get -u github.com/cosmtrek/air CMD ["air"] docker-compose.yml docker-compose.ymlを作成します。 docker-compose.yml version: "3" services: go: build: . volumes: - ./:/go/src/app ports: - "8080:8080" air.tomlを作成する Airのリポジトリ に公開されている設定ファイルを使わせてもらいます。 air.toml # Config file for [Air](https://github.com/cosmtrek/air) in TOML format # Working directory # . or absolute path, please note that the directories following must be under root. root = "." tmp_dir = "tmp" [build] # Just plain old shell command. You could use `make` as well. cmd = "go build -o ./tmp/main ." # Binary file yields from `cmd`. bin = "tmp/main" # Customize binary, can setup environment variables when run your app. full_bin = "APP_ENV=dev APP_USER=air ./tmp/main" # Watch these filename extensions. include_ext = ["go", "tpl", "tmpl", "html"] # Ignore these filename extensions or directories. exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"] # Watch these directories if you specified. include_dir = [] # Exclude files. exclude_file = [] # Exclude specific regular expressions. exclude_regex = ["_test.go"] # Exclude unchanged files. exclude_unchanged = true # Follow symlink for directories follow_symlink = true # This log file places in your tmp_dir. log = "air.log" # It's not necessary to trigger build each time file changes if it's too frequent. delay = 1000 # ms # Stop running old binary when build errors occur. stop_on_error = true # Send Interrupt signal before killing process (windows does not support this feature) send_interrupt = false # Delay after sending Interrupt signal kill_delay = 500 # ms [log] # Show log time time = false [color] # Customize each part's color. If no color found, use the raw app log. main = "magenta" watcher = "cyan" build = "yellow" runner = "green" [misc] # Delete tmp directory on exit clean_on_exit = true go.modを作成する ターミナルで以下のコマンドを実行します。 $ go mod init air-sample 実行する 以下のコマンドを実行します。 running...と表示され動作していることを確認しました。 $ docker-compose up --build ... go_1 | go_1 | __ _ ___ go_1 | / /\ | | | |_) go_1 | /_/--\ |_| |_| \_ , built with Go go_1 | go_1 | watching . go_1 | !exclude tmp go_1 | building... go_1 | running... 別のターミナルをからAPIリクエストを実行してみて、レスポンスが返ってくることを確認します。 $ curl http://localhost:8080 Hello, World 次に、server.goの内容を変更します。 出力を「Hello, Gopher」に変更し、保存します。 server.go func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, Gopher") } ファイルの変更を検知してビルド走ります。 go_1 | server.go has changed go_1 | building... go_1 | running... もう一度、APIリクエストを行うとレスポンスが変化していることがわかります。 $ curl http://localhost:8080 Hello, Gopher 以上です。 参考 cosmtrek/air: ☁️ Live reload for Go apps 【Golang】 Airを用いてWebアプリケーション開発中に変更を即座に反映する - zuckey blog Golang - Official Image | Docker Hub
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

様々な開発マシンでもPhoenixが動くDockerfile/docker-composeの作り方

この記事はElixir Advent Calendar 2021の6日目です。 ごあいさつ こんにちは Koyo です!普段はコミュニティで Elixir 開発しつつ、仕事ではRuby on RailsでWebアプリケーションをごにょごにょ書いております。 さて会社外でプロジェクトに参加していると、開発マシンがMacの人もいればWSL2やLinuxもいたりとバラバラだったりしますよね。なのでDockerを用いて開発環境をなるべく統一しよう!・・・と思ったのですが、意外にハマりどころがあって苦戦したので書いてみました。 Mac WSL2 / Linux Mac / WSL2 / Linux 混在環境 の3パターンに分けて解説していきたいと思います! なお説明で使うファイルはこちらにまとめております。 想定バージョン - elixir 1.12.3 - phoenix 1.6.x Docker Desktop for Mac で Phoenix が動く Dockerfile / docker-compose こんな感じで動きます。今回はベースイメージはalpineにしてます! Dockerfile FROM elixir:1.12.3-alpine RUN apk update && apk add \ inotify-tools git build-base npm bash RUN mix do local.hex --force, local.rebar --force, archive.install --force hex phx_new docker-compose.yml version: '3' services: web: build: context: . command: mix phx.server environment: DB_HOST: db links: - db ports: - 4000:4000 volumes: - .:/work working_dir: /work db: image: postgres:9.6-alpine environment: POSTGRES_PASSWORD: postgres ports: - 5432:5432 volumes: - dbdata:/var/lib/postgresql/data volumes: dbdata: こんな感じで新しいプロジェクトも作ることができます! docker compose run --rm --no-deps web mix phx.new sample ※Docker経由でPhoenixを動作させるときの注意点 なお、実際に動作させる場合は Dockerfile と docker-compose.yml を作成したプロジェクトのディレクトリ(今回はsampleディレクトリ)にコピーするのを忘れずに。 さらに config/dev.exs の編集が必要です。 まず hostname を docker-compose.yml の環境変数で指定したホスト名にしてください。 また、ここがハマりポイントですが、デフォルトだと http: [ip: {127, 0, 0, 1}, port: 4000], になっているのを http: [ip: {0, 0, 0, 0}, port: 4000] に修正する必要があります。 config/dev.exs config :sample, Sample.Repo, ... hostname: System.get_env("DB_HOST") || "localhost", ... config :sample, SampleWeb.Endpoint, # Binding to loopback ipv4 address prevents access from other machines. # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. http: [ip: {0, 0, 0, 0}, port: 4000], Docker for Mac 以外(WSL2 / Linux など)でも動くように 上記でも Docker Desktop for Mac であれば root でコンテナを動かしてファイル生成しても、ホスト側のUID/GIDと一致するため問題ありません(ドキュメント探してもパッと見つからなかったので、理由分かる人いたら教えてくださいw)。 一方で他の環境(例えば Docker Desktop for Windows )で先ほどの mix phx.new コマンドを実行してみると以下のようになってしまいます。 $ ls -l drwxr-xr-x 9 root root 4096 Dec 5 20:24 sample/ コンテナのユーザが root であるため、作成されたファイルももちろん root になってしまいます。 mix phx.new 済みのプロジェクトであっても mix deps.get などでコンテナ経由でファイル生成することはよくあるため、これだとパーミッション周りのエラーが頻発し、困ってしまいますね。 コンテナ内にホストと同一UID/GIDのユーザを作る ということで、これを解決するために「コンテナ内にホストと同一UID/GIDのユーザを作りたい」と思います。 下準備として下記のようなMakefileを書いてみます。 Makefile .PHONY: setup setup: echo "host_user_name=${USER}" > .env echo "host_group_name=${USER}" >> .env echo "host_uid=`id -u`" >> .env echo "host_gid=`id -g`" >> .env 実行すると .env ファイルが生成されます。 $ make setup さて、これを踏まえて下記のようにDockerfile/docker-composeを作成します。 環境変数をdocker-compose.ymlに渡し、Dockerfileへはビルド時の引数という形でホストのユーザ情報を渡します。そしてコンテナビルド時にホストと同じUID/GIDのユーザが作られるようにします。 Dockerfile FROM elixir:1.12.3-alpine RUN apk update && apk add \ inotify-tools git build-base npm bash ARG host_user_name ARG host_group_name ARG host_uid ARG host_gid RUN apk add shadow && groupadd -g $host_gid $host_group_name \ && useradd -m -s /bin/bash -u $host_uid -g $host_gid $host_user_name USER $host_user_name RUN mix do local.hex --force, local.rebar --force, archive.install --force hex phx_new docker-compose.yml version: '3' services: web: build: context: . args: - host_user_name=${host_user_name} - host_group_name=${host_group_name} - host_uid=${host_uid} - host_gid=${host_gid} command: mix phx.server environment: DB_HOST: db links: - db ports: - 4000:4000 volumes: - .:/work working_dir: /work db: image: postgres:9.6-alpine environment: POSTGRES_PASSWORD: postgres ports: - 5432:5432 volumes: - dbdata:/var/lib/postgresql/data volumes: dbdata: さて、これで実行してみると今度はrootにならずにできていますね! $ docker compose run --rm web mix phx.new sample ... $ ls -l drwxr-xr-x 9 koyo koyo 4096 Dec 5 20:52 sample/ Mac / WSL2 / Linux 混在環境でも動くように これで解決・・・と思いきや Mac 環境で上記の Dockerfile をビルドしてみると問題が発生してしまいます。 どうも Mac 側の GID と衝突してしまうよう・・・(いい回避策知ってたら教えてくださいw)。 > [3/4] RUN apk add shadow && groupadd -g 20 koyo && useradd -m -s /bin/bash -u 504 -g 20 koyo: #6 0.388 (1/2) Installing linux-pam (1.5.1-r1) #6 1.901 (2/2) Installing shadow (4.8.1-r0) #6 1.962 Executing busybox-1.33.1-r6.trigger #6 1.968 OK: 264 MiB in 55 packages #6 2.008 groupadd: GID '20' already exists プロジェクトがMacのみ!とかMac以外のみ!であれば、上記のどちらかを選択して使えばいいかと思います。 しかし実際には混在していることが多いのではないでしょうか。 筆者が参加したプロジェクトでは Mac / WSL2 / Linux と様々なOSで開発している方が集まっていました笑 ということで頑張ってみましょう! …とその前に、 docker-compose.yml を上書きする手法と、マルチステージビルドについて説明します。 docker-compose の設定を上書きする docker compose コマンドは標準で docker-compose.override.yml という上書き用のファイルをサポートしています。これが存在する場合 docker-compose.yml の設定を docker-compose.override.yml で上書きしてくれます。 マルチステージビルド Dockerfile には実は「複数のFROM」を書くことができます。例えば1つ目のFROMフェーズでビルドを行い、そこで作成したビルド結果だけを後続のステージに渡すことで、コンテナ容量を削減できます。 今回はこちらをビルド処理の共通化に使ってみたいと思います。 Dockerfile FROM ... AS base FROM base AS ... Mac / WSL2 / Linux 混在環境でも動く Dockerfile/docker-compose.yml まず Dockerfile を以下のようにします。 base フェーズで共通の処理を行い、その後 setup_user フェーズを経由してユーザを作成する build_as_user と、経由せずユーザを作成しない build_as_root フェーズに分岐します。 Dockerfile FROM elixir:1.12.3-alpine AS base RUN apk update && apk add \ inotify-tools git build-base npm bash FROM base AS setup_user ARG host_user_name ARG host_group_name ARG host_uid ARG host_gid RUN apk add shadow && groupadd -g $host_gid $host_group_name \ && useradd -m -s /bin/bash -u $host_uid -g $host_gid $host_user_name USER $host_user_name FROM setup_user AS build_as_user RUN mix do local.hex --force, local.rebar --force, archive.install --force hex phx_new FROM base AS build_as_root RUN mix do local.hex --force, local.rebar --force, archive.install --force hex phx_new docker-compose.yml では target: build_as_root とすることでユーザを作成せずビルドが行われるようにしておきます。 docker-compose.yml version: '3' services: web: build: context: . target: build_as_root command: mix phx.server environment: DB_HOST: db links: - db ports: - 4000:4000 volumes: - .:/work working_dir: /work db: image: postgres:9.6-alpine environment: POSTGRES_PASSWORD: postgres ports: - 5432:5432 volumes: - dbdata:/var/lib/postgresql/data volumes: dbdata: このままだと Docker Desktop for Mac 環境でしか動かないため、ここからさらに手を加えます。 まず docker-compose.yml とは別のディレクトリに以下の docker-compose.override.yml を配置します。 target: build_as_user とすることでユーザを作成してビルドが行われるようにしつつ、環境変数経由でホストのユーザ情報をDockerfileに渡します。 docker/docker-compose.override.yml services: web: build: target: build_as_user args: - host_user_name=${host_user_name} - host_group_name=${host_group_name} - host_uid=${host_uid} - host_gid=${host_gid} そして Makefile を以下のようにして、 docker/docker-compose.override.yml を docker-compose.yml があるディレクトリにコピーするようにしておきます。 Makefile .PHONY: setup_for_non_mac setup_for_docker_user: cp docker/docker-compose.override.yml . echo "host_user_name=${USER}" > .env echo "host_group_name=${USER}" >> .env echo "host_uid=`id -u`" >> .env echo "host_gid=`id -g`" >> .env こうすることで 「Macユーザはそのまま、そうでない場合は make setup_for_docker_user を実行してもらう」 とすることで、異なるOSが混在する環境でも Elixir/Phoenix を動作させることができます!あとは README.md にでも書いておくといいですね。 便利! まとめ Mac WSL2 / Linux Mac / WSL2 / Linux 混在環境 で動く Dockerfile と docker-compose.yml を作ってみました。特に「Mac / WSL2 / Linux 混在環境」で動くようにするのにだいぶ苦労したので、ぜひ使ってください笑 今回のDockerfileは一例ですので、alpineを使わないようにしてみるなど、プロジェクトの構成に併せて適宜カスタマイズしてみてください!(alpine使わずに動かす Dockerfile 書いたらぜひ記事にして教えてください!) 今回紹介したDockerfile群はこちらのリポジトリで公開しています! READMEにも動かし方を書いてあるので参考にしてみてください^w^ 私の記事はここでおしまいです!明日は @kn339264 のElixir初心者向けコミュニティを作った話です! ぜひぜひ読んでみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows PCでDocker Desktopを利用せずにLinuxコンテナーとWindowsコンテナー環境を構築する方法

はじめに 先日、Docker Desktopの有償化がアナウンスされました。大規模な組織などが有償化の対象となりますので、利用されている該当組織では対応の検討・実施が必要です。中にはDocker Desktopを利用しない代替案を検討している方々もいらっしゃると思います。 本記事では、Windows PC (Windows10/11などのクライアント環境)でのDocker Desktopの代替案について、その構築手順を紹介したいと思います。特に、LinuxコンテナーをWindows PCで実行する方法だけでなく、Windowsコンテナーの環境構築についても紹介ています。 Linuxコンテナー環境の構築、Windowsコンテナー環境の構築の順に説明していますが、Windowsコンテナー環境だけを構築したい方は、そちらの手順だけを実施しても問題ありません。 Linuxコンテナー環境構築 Widows PCでLinuxコンテナーを稼働させる方法はいくつかあると思います。最近ではWindows Subsystem for Linux (WSL)の利用が一般的になっており、Docker Desktopでもこの方法を利用できます。そこで本記事ではDocker EngineをWSLの環境で利用し、Linuxコンテナー環境の構築する手順を説明していきます。 (1)Windows PCへのWSLのインストール Windows PCにおいて、管理者権限のPowershellまたはコマンドプロンプトで下記のコマンドを実行します(参考 MicrosoftのWSLインストールに関するドキュメント)。これにより、WSLに必要なWindowsの機能やLinuxのディストリビューションがインストールされます。完了には再起動が必要になります。なお、デフォルトではLinuxディストリビューションとしてubuntuがインストールされますが、変更可能です。詳細はこちらのドキュメントを参照ください。本記事では、ubuntuを前提に続く手順を説明します。 再起動後にubuntuのコンソールが開き、最初にubuntuのユーザ名やパスワードの設定を実施します。 wsl --install (2)WSLへのDocker Engineのインストール WSLの構築が完了すれば、あとはDocker Engineを一般的なLinuxにインストールする手順と同様です。WSLのubuntuコンソールで、Dockerのドキュメントに記載の手順に従い、下記の手順でubuntuにDocker Engineをインストールします。 #パッケージインデックスのアップデート sudo apt-get update #前提ツールのインストール sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release #GPGキーの追加 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg #Dockerのstableリポジトリの追加 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null #リポジトリ追加後のパッケージインデックスの再アップデート sudo apt-get update #最新バージョンのDocker Engineとコンテナランタイム(containerd)のインストール sudo apt-get install docker-ce docker-ce-cli containerd.io なお、インストールするDocker engineのバージョン指定も可能です。方法はこちらのドキュメントを参照してください。 (3)Docker Engineの起動とコンテナーの実行 Docker Engineのインストールが完了したら、WSLのubuntuコンソールで下記のコマンドを実行してDocker Engineを起動できます。 sudo service docker start ここでテスト用のコンテナーを起動してみます。下記のコマンドでテスト用のhello-worldコンテナーを実行します。(sudoを付けずに実行する方法については後述します) sudo docker run hello-world 上記コマンドの実行後、コンテナーが問題なく実行された場合は、下記ようなメッセージが表示されます。 Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ これで無事にWindows PCのWSL上にDocker Engineを用いたLinuxコンテナーの実行環境が構築できました! (補足)ユーザグループ設定 最後に、dockerコマンドをroot権限(sudo)ではなくユーザ権限で実行可能する方法を説明します。Docker Engineのデフォルトではdockerというグループが設定されていますので、こちらのグループにDocker Engineを利用したいユーザを下記のように追加します。 sudo usermod -a -G docker <ユーザ名> Windowsコンテナー環境構築 個人的にはこちらが本記事のメイントピックスです。ここからはWindowsコンテナーをWindows PCでネイティブに実行できるように環境構築する方法を説明します。Windowsコンテナー環境だけを構築したい方は、こちらの手順だけを実施ください。これには、Docker Engineのバイナリーパッケージを利用したインストールを利用します。 (1)Dockerバイナリーパッケージのダウンロードと展開 まず、Windows PCでPowerShellを開き、下記のコマンドで任意のフォルダーにパッケージをダウンロードし、インストール先に展開します。この記事執筆時点では最新パッケージがdocker-20.10.11.zipでしたので、そちらを利用しています。もちろんブラウザーでバイナリーパッケージのページを開いてダウンロードし、エクスプローラーで展開しても問題ありません。 #バイナリーパッケージのダウンロード(ダウンロードするフォルダで実行) curl.exe -O https://download.docker.com/win/static/stable/x86_64/docker-20.10.11.zip #パッケージのインストール先への展開(この例ではC:\dockerというフォルダー名に展開されます) Expand-Archive docker-20.10.11.zip -DestinationPath C:\ 上記手順の結果、インストール先に実行ファイルが展開されるので、環境変数のPathを設定します。下図の例ではWindowsのスタートメニューから「システム環境変数の編集」を検索して開き、環境変数の設定ウインドウでシステム環境変数のPathに、今回DockerをインストールしたC:\dockerを追加しています。 (2)Windowsのコンテナー機能の有効化 Windowsコンテナー実行の前提となる、Windowsのコンテナー機能を有効化します。これには、スタートメニューから「Windowsの機能の有効化または無効化」を検索して開き、「コンテナー」のチェックをオンにしてOKボタンをクリックします。 (3)Docker Engineの起動 インストールされたdockerd.exeをバックグラウンドで起動します。管理者権限でPowerShellを起動し、下記のコマンドを実行します。新しいウインドウが開き、dockerdの実行の様子が表示されます。 Start dockerd なお、このDocker EngineをWindowsのサービスとして起動可能です。下記コマンドのように、dockerdの--register-serviceオプションを指定することで、Docker EngineがWindowsのサービスに登録され、起動できます。これによりWindows起動時にも自動起動されます。 #WindowsサービスにDocker Engineを登録 dockerd --register-service #Docker Engineサービスの起動 Start-Service docker (4)Windowsコンテナーの実行 Windowsコンテナーの実行に関しては、まずWindowsコンテナーは2種類の分離モードが存在することに注意が必要です。これによって利用できるコンテナーイメージの互換性が異なります。Docker Engineのデフォルトでは、分離にHyper-Vを利用するモードが設定されていますが、利用環境のWindows PCでHyper-Vの機能が有効化されている必要があります。一方、プロセス分離モードを利用する場合、dockerコマンドの--isolationオプションで明確に指定するか、デフォルト設定を変更(後述)する必要があります。 どちらのモードで利用するかはコンテナーの実行要件に依存します。特に、Windowsを実行する環境が仮想化をサポートしていない場合(例えば仮想サーバ上で稼働しているが入れ子になった仮想化をサポートしていない場合)や、組織のポリシー等でHyper-Vの有効化ができない環境の場合には、プロセス分離モードを選択することになります。 Hyper-V分離の場合は、dockerコマンドを用いてそのままコンテナーを実行します。一方、プロセス分離の場合は、--isolation=processを指定して実行し、さらにホストOSのバージョンと互換性があるベースコンテナーイメージを選択する必要があります。 #Hyper-V分離の場合 docker run --rm -it mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd.exe #プロセス分離の場合(この例ではWindows11バージョン21H2環境で実行しているため、ltsc2022のタグのコンテナーイメージを利用) docker run --isolation=process --rm -it mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd.exe どちらも、実行後に下記のようなコンテナー内部のコマンドコンソールが表示されれば無事にコンテナーが実行されています。exitコマンドでコンテナーを終了します。 Microsoft Windows [Version 10.0.22000.350] (c) Microsoft Corporation. All rights reserved. C:\> これで無事にWindows PCでのWindowsコンテナーの実行環境が構築できました! (補足)Windowsコンテナー実行環境のデフォルト分離モード・ユーザーグループ設定 ここでは、Windowsコンテナーのデフォルト分離モード、およびユーザグループの設定について補足します。前述の通り分離モードはデフォルトでHyper-Vが指定されていますので、プロセス分離を利用する場合はコンテナー実行時に毎回オプションを指定する必要があります。また、デフォルトの状態では、dockerコマンドを実行するには管理者権限のコンソールを利用する必要があります。これらはDocker Engineの設定により変更できます。 Docker Engineの設定の方法として、dockerd.exeのオプションとして指定する方法と、構成ファイルを利用する方法があります。構成ファイルについてはMicrosoftのドキュメントに詳しい説明がありますので、こちらを参照ください。ここでは、dockerd.exeのオプションを利用して簡単に設定する方法について紹介します。 dockerd.exeのオプションのうち、分離モードの指定オプションは--exec-optです。また、ユーザーグループを設定するオプションは-Gもしくは--groupです。Windowsのユーザーグループを作成しておき、このオプションで当該ユーザーグループ名を指定することで、当該ユーザーグループに登録されたユーザーは、管理者権限のコンソールを開くことなくコンテナー実行環境を利用できます。これをdockerdの起動時やサービスの登録時に指定することで、簡単に指定できます。下記にサービス登録時のオプション指定方法の例を示します。 #分離モードをプロセス分離に設定し、ユーザーグループを設定してWindowsサービスに登録 dockerd --register-service --exec-opt "isolation=process" -G <ユーザーグループ名> [参考]クラウドを用いたコンテナーのビルドと簡単な検証 もし、コンテナーのビルド環境としてDocker Desktopを主に利用し、コンテナーの実行は簡単な検証のみに利用していた場合には、別の代替案があります。 AzureのプライベートなコンテナーレジストリーであるAzure Container Registryでは、コンテナーのビルドや簡単な検証を実施できる機能があります。詳細はここでは説明しませんが、興味のある方はこちらのMicrosoftドキュメントを参照ください。もちろんLinuxコンテナーだけでなくWindowsコンテナーのビルドや実行テストにも対応しています。AzureのサブスクリプションとAzure Container Registryの準備は必要ですが、Windows PCなどのクライアント環境では、AzureのコマンドラインツールであるAzure CLIさえインストールされていれば利用することができます。 例えば、Dockerfileやソースコードなどが存在するフォルダで下記のコマンドを実行すれば、コンテナーをビルドしてAzure Container Registryにプッシュする動作が実行されます。 #Linuxコンテナーのビルドとレジストリーへのプッシュ az acr build --image <イメージ名・タグ> --registry <レジストリ名> . #Windowsコンテナーのビルドとレジストリーへのプッシュ(--platformオプションでWindowsを指定) az acr build --image <イメージ名・タグ> --registry <レジストリ名> --platform windows/amd64 . さいごに 本記事では、Windows PCのLinuxコンテナーおよびWindowsコンテナーの環境をDocker Desktopを利用せずに、Docker Engineを利用して構築する方法についてご紹介しました。しかし、Docker Desktopには様々な追加機能があり、Docker Engineに比べで様々な利点があります。それらを利用したい場合には、やはりDocker Desktopの利用継続を検討すべきと思います。また、ここでご紹介した方法以外にも、podmanなどさまざまな別の方法もあります。さらに同様のテーマの記事も多数ありますので、そちらもぜひ参照して、ご自身に合った方法を検討ください。個人的には、Windowsコンテナー環境の構築に関する情報は、もっと広がるべきと思っています。 本記事がコンテナーを日々活用されている皆様の参考意見の1つとなり、少しでも助力になれば幸いです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【環境構築】macOS Big Sur 11.6.1 + Dockerのpython containerにpandasをinstall

会社貸与のMacBook Proに飲み物をこぼしてしまい動かなくなったので交換してもらった。 前のマシンにはPythonやらPandasやら使いたいライブラリーを直接インストールしていたので、環境のトラブルがあった場合に色々と面倒だった。今回は素直にDockerで環境構築して、いざとなればimage捨てて作り直せばいいやと思い、環境構築の手順をロギング。 pyhtonのcontainer実行できるようになったので、自分の仕事の効率化のために書いたpythonコード実行する環境を再構築する。 ということで、今回はpandsをinstall 前回までの記事 【環境構築】macOS Big Sur 11.6.1 にDockerをInstall https://qiita.com/cocoapuff/items/e3eee747b1aeafa32037 【環境構築】macOS Big Sur 11.6.1 + Dockerでpython https://qiita.com/cocoapuff/items/1daaf9e91b24bc3818ad pandsをインストール pythonのcontainerは動いている前提 自分macにはpipをinstallしていないので、間違ってMacのterminalで実行しても問題ないけど、cpntainer側のCLIで実行するよう気をつける # pip3 install pandas これだけです。 pandasを使ったpythonコードを実行してみる pandasをimportして使えていることを確かめる簡単なコードを書いて実行してみる pandas_test.py import pandas as pd df = pd.DataFrame( { 'name':['itoh', 'saitoh'], 'age':['20', '30'] }) print(df) # python ./pandas_test.py name age 0 itoh 20 1 saitoh 30 問題なく動いたので、pandasは使える 今日はここまで。 container内でコード書くの大変なのでVScodeで書けるようにしたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

とにかくすぐにApacheが欲しいときのdockerコマンド

# docker run --rm -p 80:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd:2.4 $ curl localhost <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <html> <head> <title>Index of /</title> </head> <body> <h1>Index of /</h1> <ul></ul> </body></html> Httpd - Official Image | Docker Hub
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

herokuへのコンテナデプロイでのエラー ActiveSupport::MessageEncryptor::InvalidMessage:

我らが山浦清透大先生のこの動画の通りに,herokuへのコンテナデプロイをしようとしてます。 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage このようなエラーがでてきた。 secret_key_base config/master.key config/credentials.yml.enc 暗号化/複合化。 なんか聞いたことある。 端的にcredentials.yml.encの文字列とmaster.keyの文字列の組み合わせが不正解であるということです。 heroku config:set RAILS_MASTER_KEY=`cat config/master.key` を実行 これを実行したらエラー解決できるとキータの記事にあった() heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks エラー変わらず。 heroku config -a ideaframeworksで RAILS_MASTER_KEY:がちゃんと設定されていた。 ローカルのmaster.keyと同じなのに。。。。。 戯れにgit push heroku masterを実行 soichirohara@SoichironoMacBook-Pro ideaFrameworks % git push heroku master Enumerating objects: 321, done. Counting objects: 100% (321/321), done. Delta compression using up to 8 threads Compressing objects: 100% (285/285), done. Writing objects: 100% (321/321), 219.98 KiB | 5.95 MiB/s, done. Total 321 (delta 98), reused 0 (delta 0), pack-reused 0 remote: Compressing source files... done. remote: Building source: remote: === Fetching app code remote: remote: =!= Your app does not include a heroku.yml build manifest. To deploy your app, either create a heroku.yml: https://devcenter.heroku.com/articles/build-docker-images-heroku-yml remote: Or change your stack by running: 'heroku stack:set heroku-20' remote: Verifying deploy... remote: remote: ! Push rejected to ideaframeworks. remote: To https://git.heroku.com/ideaframeworks.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/ideaframeworks.git' heroku.yml build: docker: web: Dockerfile.production heroku.ymlでイメージをビルドしてdeployできるとかなんとか Dockerfile.production FROM ruby:2.6.5 ENV RAILS_ENV=production ## nodejsとyarnはwebpackをインストールする際に必要 # yarnパッケージ管理ツールをインストール RUN curl http://deb.debian.org/debian/dists/buster/main/binary-amd64/by-hash/SHA256/935deda18d5bdc25fb1813d0ec99b6e0e32a084b203e518af0cf7dc79ee8ebda | head RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ 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 yarn && apt-get install -y graphviz RUN /bin/sh -c /bin/sh -c bundle update --bundler RUN gem install bundler:2.1.4 RUN mkdir /ideaFrameworks WORKDIR /ideaFrameworks COPY . /ideaFrameworks COPY Gemfile /ideaFrameworks/Gemfile COPY Gemfile.lock /ideaFrameworks/Gemfile.lock RUN bundle install COPY start.sh /start.sh RUN chmod 744 /start.sh CMD ["sh","/start.sh"] heroku stack:set container git push heroku master を実行。 Post-install message from rubyzip: remote: RubyZip 3.0 is coming! remote: ********************** remote: remote: The public API of some Rubyzip classes has been modernized to use named remote: parameters for optional arguments. Please check your usage of the remote: following classes: remote: * `Zip::File` remote: * `Zip::Entry` remote: * `Zip::InputStream` remote: * `Zip::OutputStream` remote: remote: Please ensure that your Gemfiles and .gemspecs are suitably restrictive remote: to avoid an unexpected breakage when 3.0 is released (e.g. ~> 2.3.0). remote: See https://github.com/rubyzip/rubyzip for details. The Changelog also remote: lists other enhancements and bugfixes that have been implemented since remote: version 2.3.0. remote: Removing intermediate container abde761777fb remote: ---> 591c8c89978c remote: Step 13/15 : COPY start.sh /start.sh remote: COPY failed: stat /var/lib/docker/tmp/docker-builder709159940/start.sh: no such file or directory remote: remote: Verifying deploy... remote: remote: ! Push rejected to ideaframeworks. remote: To https://git.heroku.com/ideaframeworks.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/ideaframeworks.git COPY failed start.shが消えていたので、 start.sh #!/bin/sh if ["${RAILS_ENV}"="production"] then bundle exec rails assets:precompile fi bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0 を作成して コミット,pushして再度 git push heroku master というかビルドする方法をすこし変えただけなので、 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: が出るエラーは多分変わらん。 根本的な問題はそこではない。 どうしてもできない場合は、 credentials.yml.encを一度消して、$ EDITOR="vi" bin/rails credentials:editを再度実行することで、credentials.yml.encとmaster.keyが新しく作り直されます とあるので、こうしたら秘密鍵と公開鍵が合致する可能性もある。 が、そこらへんをいじるのはこわいので最終手段。 なにはともあれ deploy成功した。ので heroku run bundle exec rails db:migrate RAILS_ENV=production soichirohara@SoichironoMacBook-Pro ideaFrameworks % heroku run bundle exec rails db:migrate RAILS_ENV=production - Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.3070 (Free) rails aborted! ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage /ideaFrameworks/config/environment.rb:5:in `' Caused by: OpenSSL::Cipher::CipherError: /ideaFrameworks/config/environment.rb:5:in `' Tasks: TOP => db:migrate => db:load_config => environment (See full trace by running task with --trace) config/enviroment.rb Rails.application.initialize! この方も自分と同じエラーで、master.keyとcredentials.yml.encの削除 EDITOR="vi" bin/rails credentials:edit をすればいいらしい。 もうこれしかねぇ。 master.keyが再度作られない。。。。 この記事によるとsudoをやらないといけないらしい master.keyとcredentials.yml.encの削除して sudo EDITOR="vi" rails credentials:edit sudo権限を付与したら両方つくられた。 sudo vi config/master.key これでmaster.keyの値もみれた。 新しくつくられたmaster.keyの値もセットした heroku run bundle exec rails db:migrate RAILS_ENV=production お願いします!!!! エラー変わらず。。。。 credentials.yml.encを書き換えたあとにpushしわすれた。 git push heroku masterを実行 これでcredentials.yml.encとmaster.keyの値は一致するはず。 heroku run bundle exec rails db:migrate RAILS_ENV=production お願いします!!!! LoadError: Error loading the 'postgresql' Active Record adapter. Missing a gem it depends on? pg is not part of the bundle. Add it to your Gemfile. Caused by: Gem::LoadError: pg is not part of the bundle. Add it to your Gemfile. Tasks: TOP => db:migrate => db:load_config (See full trace by running task with --trace) エラー内容が変わった!やったぜ! これはheroku ポスグレのアドオンがideaframeworksに入っていたので、削除して、 再度 heroku run bundle exec rails db:migrate RAILS_ENV=production Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.4267 (Free) rails aborted! ActiveRecord::ConnectionNotEstablished: Unknown MySQL server host 'db' (-2) Caused by: Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2) Tasks: TOP => db:migrate (See full trace by running task with --trace) エラーが変わりましたね。 database.yml production: <<: *default database: ideaFrameworks_production username: ideaFrameworks password: <%= ENV['MYSQL_ROOT_PASSWORD'] %> のプロダクションがこうなってました。 以前、設定した値が何故か吹きとんでたので この動画のまんまの設定にして database.yml production: <<: *default database: <%= ENV['APP_DATABASE'] %> username: <%= ENV['APP_DATABASE_USERNAME'] %> password: <%= ENV['APP_DATABASE_PASSWORD'] %> host: <%= ENV['APP_DATABASE_HOST'] %> に設定しなおして git pushとgit push heroku master して heroku run bundle exec rails db:migrate RAILS_ENV=production これでいけるだろ!!! soichirohara@SoichironoMacBook-Pro ideaFrameworks % heroku run bundle exec rails db:migrate RAILS_ENV=production Running bundle exec rails db:migrate RAILS_ENV=production on ⬢ ideaframeworks... up, run.8668 (Free) I, [2021-12-05T06:50:22.412316 #4] INFO -- : Migrating to CreateMandalarts (20211202075545) == 20211202075545 CreateMandalarts: migrating ================================= -- create_table(:mandalarts) -> 0.0229s == 20211202075545 CreateMandalarts: migrated (0.0230s) ======================== きた=======!!!!!!! まとめると ここまでうまくいってる前提で話します。 heroku run bundle exec rake db:migrate RAILS_ENV=production -a ideaframeworks を実行したら ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage というエラーがでてきた。 どうやら、credentials.yml.encの文字列とmaster.keyの文字列の組み合わせが合ってないらしい。 この記事を参考に、 master.keyとcredentials.yml.encの削除して sudo EDITOR="vi" rails credentials:edit sudo権限を付与したら両方つくられた。 sudo vi config/master.key これでmaster.keyの値もみれた。 新しくつくられたmaster.keyの値もheroku config:set とかでセットして、 git push origin master git push heroku master か、 heroku container:push とか 個人的には、heroku.ymlのほうが ビルドするDockerfileも指定しやすくて好き。 んで、どっちかのコマンドを打ったら、 master.keyとcredentials.yml.encが合致するので、うまくいくはず。 おまけ Dockefile.production FROM ruby:2.6.5 ENV RAILS_ENV=production ## nodejsとyarnはwebpackをインストールする際に必要 # yarnパッケージ管理ツールをインストール RUN curl http://deb.debian.org/debian/dists/buster/main/binary-amd64/by-hash/SHA256/935deda18d5bdc25fb1813d0ec99b6e0e32a084b203e518af0cf7dc79ee8ebda | head RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ 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 yarn && apt-get install -y graphviz RUN /bin/sh -c /bin/sh -c bundle update --bundler RUN gem install bundler:2.1.4 RUN mkdir /ideaFrameworks WORKDIR /ideaFrameworks COPY . /ideaFrameworks COPY Gemfile /ideaFrameworks/Gemfile COPY Gemfile.lock /ideaFrameworks/Gemfile.lock RUN bundle install COPY start.sh /start.sh RUN chmod 744 /start.sh CMD ["sh","/start.sh"] start.sh #!/bin/sh if ["${RAILS_ENV}"="production"] then bundle exec rails assets:precompile fi bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0 heroku.yml build: docker: web: Dockerfile.production これで,git push heroku masterでデプロイができるので良き
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでCentOS7(PHP7.4 Apatch2.4 MySQL8)を構築してSSHで外部から接続するまで

CentOS7 説明 CentOS7のコンテナ内でphpとapatchを構成し、MySQLは別のコンテナを用意してCentOSから接続をする。 ディレクトリ構成 centos ├── Dockerfile └── php └── php.ini docker-compose.yml html └── index.php MySQL └── data docker-compose.yml version: '3.0' services: web: build: "./centos7" container_name: "centos7" ports: - 80:80 - 20022:20022 volumes: - "./html:/var/www/html" command: /sbin/init privileged: true db: image: mysql:8.0 environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' ports: - "3306:3306" volumes: - ./mysql/data:/var/lib/mysql depends_on: - web Dockerfile FROM centos:7 RUN yum -y update && yum clean all # Repository # EPEL RUN yum install -y epel-release # remi RUN yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm # Apache2.4 インストール RUN yum -y install httpd # Apacheの自動起動設定 RUN systemctl enable httpd # PHP7.4 インストール RUN yum -y install --enablerepo=remi,remi-php74 php php-devel php-mbstring php-pdo php-xml php-gd php-fpm php-mysqlnd php-opcache php-pecl-zip libzip5 # php.iniコピー # COPY ./php/php.ini /etc/php.ini # vim インストール RUN yum -y install vim # SSH接続ここから-------- RUN yum -y update \ && yum install -y openssh-server \ openssh-clients \ && yum clean all # rootでのログインを許可 # ポートを22から20022に変更 # rootのパスワードをpasswordに設定 RUN sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config \ && sed -ri 's/^#Port 22/Port 20022/' /etc/ssh/sshd_config \ && echo 'root:ronaldo7' | chpasswd EXPOSE 20022 # SSH接続ここまで-------- CMD ["/sbin/init"] php.ini [Date] date.timezone = "Asia/Tokyo"; [mbstring] mbstring.internal_encording = "UTF-8" mbstring.language = "Japanese" 1. CentOS7インストール 参考URL MySQL 1. MySQLインストール 参考URL 2. MySQL設定 参考URL 3. PDO接続確認 参考URL エラー備忘録 1. PDO接続エラー SQLSTATE[HY000] [2002] No such file or directory 対応手順 1. コンテナに接続 docker container exec -it mydoker_db_1 /bin/bash 2. ホストipアドレス確認 root@a81b73e7516c:/# cat /etc/hosts //ipアドレス確認 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.30.0.3 a81b73e7516c 3. PDOのホスト名に確認したipアドレスを入力 define('HOSTNAME', '172.30.0.3'); SSH接続 1. ssh接続設定 参考URL エラー備忘録 1. composeを再構築した時に発生 //compose再構築 docker-compose build //sshで接続 ssh -p 20022 root@localhost //エラー @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ECDSA key sent by the remote host is SHA256:SoL3yQ5xw8FyrICsKI46vZRiaG1wd4BpnuBrjNO4bJ0. Please contact your system administrator. Add correct host key in /Users/user/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /Users/user/.ssh/known_hosts:1 ECDSA host key for [localhost]:20022 has changed and you have requested strict checking. Host key verification failed. 対処方法 1. ローカルPCの.sshにあるknown_hostsファイルを削除 2. ssh再接続すると新しいknown_hostsが作成され、接続できる 参考URL apatch 備忘録 1.htaccessが効かない 対処方法 httpd.confのAllowOverride Noneの設定をNONEからALLに変更 AllowOverride None ↓ AllowOverride ALL 参考URL 使ったコマンド //起動中のコンテナ確認 docker ps //全てのコンテナ確認 docker ps -a //compose起動 docker-compose up -d //compose停止 docker-compose stop //compose再構築(設定ファイル等を編集した時) docker-compose build //compose再起動 docker-compose restart //コンテナに接続 docker container exec -it mydoker_db_1 /bin/bash docker exec -it centos7 /bin/bash //apatch起動 systemctl start httpd.service systemctl restart httpd //apatch状態確認 systemctl status httpd.service //sshd再起動 systemctl restart sshd //ホストipアドレス確認 cat /etc/hosts //vimインストール yum install vim //エラー表示 ini_set( 'display_errors', 1 );
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【環境構築】macOS Big Sur 11.6.1 + Dockerでpython

会社貸与のMacBook Proに飲み物をこぼしてしまい動かなくなったので交換してもらった。 前のマシンにはPythonやらPandasやら使いたいライブラリーを直接インストールしていたので、環境のトラブルがあった場合に色々と面倒だった。今回は素直にDockerで環境構築して、いざとなればimage捨てて作り直せばいいやと思い、環境構築の手順をロギング。 今回はPythonのコンテナを起動するところまで進めたい。 前回記事 [環境構築]macOS Big Sur 11.6.1 にDockerをInstall https://qiita.com/cocoapuff/items/e3eee747b1aeafa32037 pythonのimageをpull dockerhubで良さげなimageを探す pythonで検索してみる [dockerhubより] 素直に"python"を選択する [dockerhubより] "Official image"ということで、まずはこのimageを使ってライブラリーはお好みで追加することにする。 ここから先はCLIで作業が必要になってきた。 仕方が無いので、とりあえずTerminalを起動して、pythonのimageをpullする この時、Dockerが起動していること pythonのバージョンを指定しなければ最新のものを引っ張ってくる $ docker pull python 実行結果 Using default tag: latest latest: Pulling from library/python 5e0b432e8ba9: Pull complete a84cfd68b5ce: Pull complete e8b8f2315954: Pull complete 0598fa43a7e7: Pull complete 83098237b6d3: Pull complete b92c73d4de9a: Pull complete 57f48b8baa06: Pull complete 702d43ac0fd7: Pull complete 5e2753218c06: Pull complete Digest: sha256:a1fba384d3aa879533a271ab5d73965fbd3385648f38835dacd07e519f1c7c3f Status: Downloaded newer image for python:latest docker.io/library/python:latest pythonのコンテナを起動 とりあえずpullしたimageを起動してみる プロンプトが変わる $ docker run -it --name test python /bin/bash # pythonのバージョンがいくつか確認してみる # python --version Python 3.10.0 Docker DesktopのDashboardを見てみる 動いてます "test"コンテナにマウスを当てると"CLI"を起動できる pythonコードを動かす ちゃんとpythonコードを実行できるか試してみようと思ったら、viが動かない # which vi # 無いと何かと不便なのでviをインストールする # apt-get update && apt-get -y install vim 実行結果の表示は長いので割愛 vi入った # which vi # /usr/bin/vi "Hello World"を書いて動かす # vi test.py test.py print("Hello World") # python ./test.py Hello world 動いた。今日はここまで。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

mac のファイルシステムは大文字小文字を区別しない

APFS で, 大文字小文字が区別されない. docker volume sync, tar file での動作を軽く検証する. 以下の様な動作になり、びっくり $ pwd / $ PWD / $ pWd / $ which echo /bin/echo $ which Echo /bin/Echo $ which ECHO /bin/ECHO $ WHICH ECHO /bin/ECHO $ touch abcd $ ls abcd $ touch ABCD $ ls abcd docker volumen sync した場合 docker for mac で、volumen 同期し, container 内で file を作成してみる. 結果は、mac の動作と同様に, 大文字小文字を考慮せず, 同じ file として扱われる [root@9f0e9d28a78d current]# touch a [root@9f0e9d28a78d current]# ls a [root@9f0e9d28a78d current]# touch A [root@9f0e9d28a78d current]# ls a volume 同期していない dir 内では大文字小文字は区別された [root@9f0e9d28a78d test]# touch a [root@9f0e9d28a78d test]# ls a [root@9f0e9d28a78d test]# touch A [root@9f0e9d28a78d test]# ls A a tar file を解凍した場合は? tar file の中身は以下 drwxr-xr-x 0 ./tmp/ -rw-r--r-- 2 ./tmp/A -rw-r--r-- 2 ./tmp/a 結果, 片方の file は消滅する $ tar zxvf tmp.tar.gz x ./tmp/ x ./tmp/A x ./tmp/a $ ls tmp a 怖いですね git は試していないが, 同様の動作をすると仮定すると, 惑わされる事がでてきそうですね. 怖や怖や
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでDjango3+MySQL8の環境を構築する

はじめに 初投稿です。 Dockerでdjango3+mysql8の環境を構築しようとした時に少しハマったので備忘録的な感じで書いていきます。 ※dockerについては詳しく説明できませんしません。 環境 ローカル環境 OS:macOS Big Sur Docker Desktop docker version: 20.10.7 docker-compose version: 1.29.2 作成する環境 Django=3.2 MySQL=8.0.13 環境構築 フォルダの作成 console mkdir docker-django-mysql8 cd docker-django-mysql8 touch Dockerfile docker-compose.yml requirements.txt こんな感じのディレクトリ構成になります docker-django-mysql8 |-- Dockerfile |-- docker-compose.yml |-- requirements.txt 各ファイルの作成 requirements.txt まず、requirements.txtを作成します。 pip install したいパッケージを記載します。 requirements.txt Django==3.2 mysqlclient==1.4.6 Dockerfile 次にDockerを作成します。 Dockerfile # python3のイメージを指定 FROM python:3   # バッファリングを無効化 ENV PYTHONUNBUFFERED 1  # 直下にcodeディレクトリを作成 RUN mkdir /code # codeディレクトリに移動 WORKDIR /code # codeディレクトリにrequirements.txtのコピーを配置 COPY requirements.txt /code/ # pipをupgradeしてrequirements.txtに記載したパッケージをインストールする RUN pip install --upgrade pip && pip install -r requirements.txt # docker-django-mysql8下のファイルをcodeディレクトリにコピー COPY . /code/ docker-compose.yml 最後にdocker-compose.ymlを作成します。 mysqlのイメージは提供されているものをそのまま使うためDockerfileを作成しません。 docker-compose.yml version: '3' services: web: container_name: docker-django build: . command: python3 manage.py runserver 0.0.0.0:8000 working_dir: /code ports: - 8000:8000 volumes: - .:/code #カレントディレクトリを/codeにマウント depends_on: - db db: container_name: docker-django-db image: mysql/mysql-server:8.0.13-1.1.8 command: --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_DATABASE: django MYSQL_USER: django MYSQL_PASSWORD: django MYSQL_ROOT_PASSWORD: django TZ: 'Asia/Tokyo' #codeディレクトリの/var/lib/mysqlをカレントディレクトリにマウント volumes: - ./mysql:/var/lib/mysql 必要なファイルの作成は以上でOKです docker-compose.yml command: --default-authentication-plugin=mysql_native_password このコードですが、mysql8からはログイン認証パスワード方式がデフォルトで"caching_sha2_password"に変更されており、それを従来の方式である"mysql_native_password"にdocker-compose.ymlで変更するためものです。 コンテナを立ち上げる dockerfileとdocker-compose.ymlが作成できたのでそれを元にコンテナを作成します。 docker-compose run web django-admin.py startproject project . 最後に "." をつけることを忘れないでください。 また、"project" はプロジェクト名になりますので自由に変更してください。 このコマンドを実行するとdockerfileがあるディレクトリと同階層にファイルとディレクトリが作成されていると思います。 確認してみましょう。 console ls docker-compose.yml Dockerfile manage.py mysql project requirements.txt 以上のような構成になっていることが確認できると思います。 次に、project下にあるsettings.pyのDATABASESを変更します。 project/settins.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', 'USER': 'django', 'PASSWORD': 'django', 'HOST': 'db', 'PORT': 3306, } } これで環境が構築できているはずです。 コンテナを立ち上げてみましょう。 docker-compose up http://127.0.0.1:8000 にアクセスすると、Djangoのトップページが確認できると思います。 これで環境構築は終了です。 最後に 最後まで見ていただきありがとうございました。 もし間違っている点などがあったら是非指摘していただきたいです。 問題ないようでしたらLGTMお願い致します。 また、この後のアプリの作成方法やもっと詳しく解説してほしい点など質問やお願いがありましたらお気軽にコメントお願い致します。 頑張って答えます。 ありがとうございました。 【参考】 http://hananohana.work/posts/docker_django_mysql/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Apacheをコンテナ化するコツ

Apache HTTP Server(以降Apache)をコンテナで稼働させたい場合の、コンテナ作成のコツを紹介します。 最近リバースプロキシコンテナをApacheで作成する機会があり、その時の経験から記事にしてみました。 なお、ApacheはDockerhubにて公式コンテナイメージが提供されており、こちらを使用すれば、以下のコツのうちの 1.ログを標準(エラー)出力に出す 2.Apache起動方法:daemon化しない については対応済みで特段の検討は不要です(考え方は知っておいて損はありません) 1.ログを標準(エラー)出力に出す Apacheは何も考えなければローカルディスクにアクセスログとエラーログを出すようになっています。このままコンテナ化すると、コンテナ内に入らないとログを見れないし、誰もログローテーションもしないままコンテナ内でログが肥大化し続ける事になってしまいます。 コンテナのログといえば、標準(エラー)出力に出して、コンテナ実行環境(ホスト)側に任せるというのが第一の選択肢です。 Apacheの公式コンテナも以下の通り設定ファイルで、エラーログは標準エラー出力に、アクセスログは標準出力に設定されています。 ErrorLog /proc/self/fd/2 CustomLog /proc/self/fd/1 common 2.Apache起動方法:daemon化しない Apacheの起動方法といえば多くの人が思い浮かべるのが # apachectl start が有名です。このコマンドはApacheを、daemon(デーモン)として起動します。何しろApacheの実行バイナリ名はhttpdと"d"が付くぐらいですので、ある意味当たり前の話です。 しかしコンテナで動かしたいプログラムがdaemon化しては困るので、daemon化しないでApacheを動かす必要があります。(コンテナの起動コマンドをsleep infinityにした上で裏でdaemon起動するようなことは止めましょう) ではApacheを非daemonで起動する方法は?というと、以下のコマンドを実行しましょう。 # apachectl -DFOREGROUND この-Dは様々なパラメータをApacheに与えるオプションです。FOREGROUNDは、daemon化しないで起動するためのパラメータです。1 試してみたい場合は、Apacheがインストールされた環境で、上記コマンドを実行してみて下さい。基本的にはあまり何も出ず、Apacheが実行状態になると思います。終了したい場合はCtrl+Cキーで終了できます。 apachectl startでdaemon化起動した場合は以下の動画の通り、起動コマンドは即座に終了し、バックグラウンドでApacheが動作しています。 apachectl -DFOREGROUNDで非daemon起動した場合は以下の動画の通り、起動コマンドは終了せずそのままApacheそのものになります。終了するにはCtrl+Cを押します。 よって、Apacheを動かすコンテナでは、Dockerfileに以下のように書くのが良いでしょう。 ENTRYPOINT ["/usr/local/bin/apachectl","-DFOREGROUND"] または起動用シェルスクリプトを用意し、最後に exec /usr/local/bin/apachectl -DFOREGROUND "$@" のように書きます。 なお、 # httpd -DFOREGROUND を紹介する情報も多いかと思います。httpdコマンドでも概ね結果は同じで大抵問題ありませんが、apachectlの場合はhttpdやapachectlが置かれているディレクトリのenvvarsファイルを読み込む処理などをしてからhttpdコマンドを実行するという違いがあります。 Apache公式コンテナイメージでは当然、非daemonで起動されますが、apachectlではなくhttpdを実行しています。 https://github.com/docker-library/httpd/blob/cd9f3170df90ef341c9c27fb4d17ffccd60b4ac0/2.4/httpd-foreground 3.環境変数やコマンドライン引数を活用する 頻繁に変わる値は環境変数やコマンドライン引数で外部から注入することで、汎用的にコンテナイメージを作成することが出来ます。 Apacheの場合は特に、以下のような方法で活用する事が出来ます。 3.1.環境変数値を設定ファイルで使用する Apacheは環境変数値を設定ファイルで取り込むことが出来るので、設定ファイルを文字列置換して生成するなどの処理は不要です。 具体的には、${環境変数名}の形式で設定ファイルに書くことで、起動時の環境変数値を使用することが出来ます。2 例えばポート番号を環境変数CONTAINER_PORTとした場合は、以下のように書きます。 設定例 Port ${CONTAINER_PORT} <VirtualHost *:${CONTAINER_PORT}> # いろいろな設定 </VirtualHost> なおこのように環境変数を参照する記述をした時にその環境変数が存在しない場合、${環境変数名}がそのまま文字列として設定値になり、エラーログにWARNレベルでログが出力されます。環境変数が無かったときのデフォルト値を設定する機能はApacheにはありませんので、Dockerfileか起動シェルスクリプトでデフォルト値を設定しましょう。 3.2. コマンドライン引数でフラグを渡し、設定ファイルで処理を分岐する Apacheの起動引数に、-DVARの形式でフラグを渡すことが出来ます。先ほど解説した-DFOREGROUNDもまさにこのフラグそのものです。 このフラグは、<IfDefine VAR>と</IfDefine>で囲うことで、VARが定義されている時のみ有効な設定を記述することが出来ます。 設定例 <IfDefine BASIC_AUTH_ENABLED> AuthType basic AuthName "private pages" AuthBasicProvider file AuthUserFile "/etc/htpasswd" Require valid-user </IfDefine> 3.3. 環境変数によって処理を分岐したい場合は? 3.2.をわざわざ「コマンドライン引数でフラグを渡し」として、環境変数としなかったのは、実は環境変数によって処理を分岐することは綺麗には行かない事情があるためです。 例えば、MAINTENANCE_HOST環境変数があったら、その値をホスト名としてリダイレクトをかける設定は以下のよう<If>3を使って書けば、動作します。 環境変数の有無で処理を分岐 <Location /> <If "-n osenv('MAINTENANCE_HOST')"> Redirect / https://${MAINTENANCE_HOST}/ </If> </Location> しかしこの<If>を使う方法には欠点があります。リクエストの度にこの<If>の条件のチェックが行われてしまいますので、微々たるものではありますがCPUを使います。また、リクエストの度に評価されることが原因で、<If></If>内には「ディレクトリコンテキスト」つまり<Directory>や<Location>内に書けるものしか書けません。 ${環境変数}の記述は起動時にのみ置き換え処理が走るのとは対照的です。 こんな設定をすると… <If "-n osenv('ADDITIONAL_PORT')"> Listen ${ADDITIONAL_PORT} </If> エラーになる root@3ba5dffc5a20:/usr/local/apache2/conf# export ADDITIONAL_PORT=81 root@3ba5dffc5a20:/usr/local/apache2/conf# apachectl -DFOREGROUND AH00526: Syntax error on line 554 of /usr/local/apache2/conf/httpd.conf: Listen not allowed in <If> context 仕方ないので、起動シェルスクリプトで環境変数をもとにフラグを設定することで、「2. コマンドライン引数でフラグを渡し、設定ファイルで処理を分岐する」のパターンに持ち込むしかありません。Apacheに<IfOSEnv>のようなセクションがあればそれで済むのですが…。 4.起動スクリプトを用意することを検討する 先述の通り、Apacheの設定ファイルは環境変数値を取り込むことが出来るものの、環境変数による条件分岐はあまり得意では無いため、Apache起動前に前処理としてシェルスクリプトを挟むことで解決する方法があります。 また例えばApacheで提供するコンテンツをコンテナ内に仕込むのでは無く、Amazon S3に置いておき、起動時にダウンロードして利用するとか、設定ファイルを動的に生成するとか、様々な前処理を行うことが出来ます。 前処理完了後、最後にApacheを起動しましょう。 entrypoint.sh ## 様々な前処理を実施 ## 最後にApacheを起動する exec /usr/local/apache2/bin/apachectl -DFOREGROUND "$@" 5.コンテナを非rootで動作させる Apacheはデフォルトではrootで起動した上で、子プロセスを起動した後にユーザとグループを変更するようになっています。 Apache公式コンテナイメージの設定ファイルの記述 # If you wish httpd to run as a different user or group, you must run # httpd as root initially and it will switch. # # User/Group: The name (or #number) of the user/group to run httpd as. # It is usually good practice to create a dedicated user and group for # running httpd, as with most system services. # User www-data Group www-data 親プロセスがrootで、子プロセスが一般ユーザで動作している様子 # ps u -C httpd USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 456 0.0 0.0 5916 3848 ? Ss 15:10 0:00 /usr/local/apache2/bin/httpd -k start www-data 457 0.0 0.0 1997016 9568 ? Sl 15:10 0:00 /usr/local/apache2/bin/httpd -k start www-data 458 0.0 0.0 1997016 9568 ? Sl 15:10 0:00 /usr/local/apache2/bin/httpd -k start www-data 460 0.0 0.0 1997016 9568 ? Sl 15:10 0:00 /usr/local/apache2/bin/httpd -k start 最初にrootで起動する理由は主に2つあり、 特権ポート(1024未満)でListenするため アクセスログ・エラーログをrootで追記モードでオープンするため(子プロセスがクラックされても、ログを消されないため) ですが、前者はコンテナ内で8080番などでListenして、コンテナ実行環境の機能で80番などから転送することが一般的ですし、後者はログを標準(エラー)出力に出すなら関係ありません。よって、コンテナ上でApacheを動かす時は、rootである必要はありません。 コンテナ内はコンテナ外とはLinuxカーネルの機能(名前空間)で分離されており、root権限であってもコンテナ外に影響を及ぼすことは出来ませんが、脆弱性によってこの分離が破られた時に備えて、root権限を落としておくほうがより良いです。4 やり方は、Dockerfileの適切な場所でUSER命令でユーザを指定し、Apacheの設定ファイルからUserとGroupの指定を消すだけです。 Dockerfile # コンテナをroot以外で起動する USER nobody このようにすることで、万一コンテナ内からコンテナ外にアクセス出来る脆弱性があったときも、被害がかなり抑えられます。 なお、Apache公式コンテナはこのようにはなっておらず、rootで起動するようになっています。 6.コンテナ終了時の挙動を検討する Apacheのマニュアル「停止と再起動」によると、Apacheの停止には2種類、「急な停止」と「緩やかな停止」があります。 コンテナ停止時の挙動をどちらにするか、検討する必要があります。 急な停止(stop) 緩やかな停止(graceful-stop) シグナル SIGTERM SIGWINCH 挙動 処理中のリクエストを中止してApacheを終了する 処理中のリクエストが全て完了するのを、GracefulShutdownTimeoutだけ待ってからApacheを終了する 緩やかな停止では、例えばクライアントが低速回線で大きなファイルをダウンロードしている場合にApacheの停止にとても時間がかかってしまうため、待つ最大時間を設定する事が出来ます(デフォルトでは無期限)。 緩やかな停止を採用する場合は、DockerfileにてSTOPSIGNALを指定し、コンテナ停止時にSIGWINCHを送ってもらうようにします。 Dockerfile STOPSIGNAL SIGWINCH Apacheの公式コンテナイメージも、この設定がいれてあり、「緩やかな停止」を採用しています。GracefulShutdownTimeoutは設定されておらず無期限のようです。 また、コンテナ実行環境側にもコンテナ終了までのタイムアウトが設定されていて、これを超えても終了しないコンテナはSIGKILLで強制終了されることが一般的ですので、こちらのタイムアウトも意識する必要があります。Kubernatesの場合、Pod定義でterminationGracePeriodSecondsで設定することが出来るようです。 最後に 以上、Apacheをコンテナ化するコツでしたが、いくつかの内容はApacheに限らずコンテナ一般に応用できる考え方を紹介できたと思っておりますので、是非参考にして下さい。 実はこのFOREGROUNDはあまりマニュアルにきちんと書かれていません。マニュアルはこちらです。-Dオプションのところに -DNO_DETACH (prevent the parent from forking) and -DFOREGROUND (prevent the parent from calling setsid() et al). と書かれていますが、実はFOREGROUNDのsetsid() et alのet alにはfork(2)も含まれるので、FOREGROUNDはNO_DETACHを包含しています。こんな書き方をしないで、一言「daemon化しない」と書けば分かりやすいのに…と思います。 ↩ http://httpd.apache.org/docs/2.4/en/configuring.html#syntax shell environment variables can be used in configuration file lines using the syntax ${VAR} ↩ https://httpd.apache.org/docs/2.4/en/mod/core.html#if ↩ Docker, Podman, Kubernatesなどのコンテナ実行環境では最近、ユーザ名前空間を使った"Rootlessコンテナ"機能が提供されています。この機能を使うと、コンテナ内のrootはホストのrootではなくなるので、コンテナを無理に非rootで動かす必要はないかもしれません。しかしRootlessコンテナ機能はまだ一般的とは言えませんので、それを前提とするのではなく、コンテナ側でroot権限を落としておくほうが良いです。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SATySFi+Dockerでテンプレート作った

SATySFi Advent Calendar 2021 5日目の記事です。 諏訪敬之氏によってIPAの未踏IT人材発掘・育成事業(2017)の支援の下に開発されたSATySFi は便利で高性能な組版システムですが、SATySFi のインストールチャレンジ(v0.0.6)やSATySFi インストールチャレンジ in Windows Subsystem for Linux、SATySFi インストール手引き 2021年5月版などからもわかるように、2021年になってもインストールがLaTeX同様に比較的難しい状態となっています。かくいう自分も一度は成功したものの別のパソコンにインストール失敗して挫折しています。 まだまだインストールが難しいため、amutake氏のDockerを利用する試み(リポジトリ:GitHub)やyasuo_ozu氏のバイナリ形式を利用する試み(リポジトリ:GitHub)などSATySFiの利用を楽にする試みがいくつか行われています。 そこで自分もSATySFiの利用を楽にするためにamutake氏のDockerイメージを利用してGitHubにテンプレートを作ってみました。 前提 Git、Bash、Dockerが使える状態になっていればこのテンプレートを利用できます。Windowsの場合はDockerを入れているならLinux環境に変換できるようにするターミナルも入れているはずなので、Bashも使える状態になっているはずです。1 テンプレートの紹介 先ほど述べたようにこのテンプレートはSATySFiの利用を楽にするためのテンプレートです。 このテンプレートは指定したSATySFiのパッケージの一覧をDockerイメージをビルドしたときにインストールし、そのイメージをもとにコンテナ内でコマンドを走らせることができるテンプレートとなっています。 この後で使い方を説明していきますが、より詳しくはREADMEを確認してください。 問題や要望などはissueやPRにお願いします。 テンプレートを使ってPDFを生成する テンプレートからPDFを生成するまでのStepは7つあります。 今回説明のために自分もサンプルを作成しているのでこちらも参考にしてみてください。 Step1:リポジトリ作成 まず、リポジトリを作成していきます。テンプレートからリポジトリを作成するのは、クローンするときと同じ緑色のボタンからできます。この緑色のボタンを押していろいろ設定するとリポジトリが出来上がります。 Step2:リポジトリのクローン 次に、作成したリポジトリをクローンしてローカルで編集できるようにします。クローンした後は、bashコマンドが使えるLinux風のパスが扱えるターミナルでそのリポジトリルートディレクトリを開いておきます。 クローン時に注意してほしいのがGitのAutoCrlf設定です。設定次第でWindowsでは改行コードがCR+LFで保存されてしまい、Bashの実行時に¥rコマンドがわからないなどと言われてしまいます。これを直すには対象ファイルを適当なエディタで開いて改行コードをLFにして保存するか、Gitでクローンしてくるときに改行コードをLFで取ってくるように設定するかする必要があります。 Step3:.project-envの設定 ローカル環境で開発環境を用意したので次は環境の設定を行っていきます。環境の設定は.project-envファイルで行います。このファイルはいわゆるenvファイルです。設定項目は四つあります。以下、.project-envで設定できる項目の設定値は$変数名と表記します。 一つ目はmeta情報です。 projectRoot=$(git rev-parse --show-cdup) workspace="$projectRoot/workspace" projectRootはリポジトリのルートで、workspaceはsatyファイルやpdfファイルを配置するフォルダのパスです。 これらは変える必要はないので今回はそのままです。 二つ目はプロジェクトの情報です。 author=ogata-k projectName=satysfi_sample authorは作者、projectNameはプロジェクト名です。デフォルトでは \$author/$projectNameでDockerのイメージ名になるのでprojectNameはDockerイメージとして解決できる名前にしておく必要があります。 今回は適当に名前つけておきます。 三つめはDockerの情報です。 dockerTag=${satysfiVersion:-0.0.6} dockerRoot="$projectRoot/docker" dockerImage="$author/$projectName:$dockerTag" dockerFileName=Dockerfile dockerTagはベースイメージのamutake/satysfiの全部入りイメージのタグ、dockerRootはDockerFileを置いてあるファイル、dockerImageはDockerイメージの名前、dockerFileNameはDockerfileの名前です。 SATySFiの最新が2021/12/05現在で0.0.6なので今回はデフォルトのままです。 四つ目は$workspace下のSATySFi関係のファイルについてです。 mainSrcFileName=main.saty mainPdfFileName=satysfi-sample.pdf mainSrcFileNameはメインのソースファイル、mainPdfFileNameはメインのソースファイルの変換先PDFファイルです。 デフォルトのままだとうまく書き出されたかわからないのでmainPdfFileNameだけ今回は変えておきます。 以上で、.project-envファイルの設定は完了です。 Step4:.satysfi-packagesの設定 次に利用したいSATySFiのパッケージを指定していきます。 .satysfi-packagesファイルをline-formatのフォーマットで改行区切りで以下のように記述していきます。 # line-format = <line> # <line> = '[:space:]*<package>?[:space:]*<comment>?' # <package> = '<package name without 'satysfi-'>((\.[:digit:]+){3})?' # <comment> = '#.*' // ex. 以下記入例 # base utility base.1.4.0 siunitx.0.1.1 # SI unit extend uline # ruby.0.1.2 # Japanese only #latexcmds.0.1.0 2021/12/05現在で列挙されているパッケージはpuripuri2100氏にこちらのツイートで教えていただいたものです。 Step5:Dockerイメージをビルドする .package-envと.satysfi-packagesファイルの設定が完了したのでDockerイメージを作成します。 Git管理下からたどるならどこでもよいですが、今回は$projectRoot直下で次のコマンドをたたきます。 ./cmd/build-docker.sh ビルドに成功すると\$dockerImageのイメージが出来上がります。同時に、ローカルでもSATySFiパッケージを参照できるように$workspace下の.satysfiフォルダ下にパッケージ情報が吐き出されます。 これでPDFを吐き出す環境が整いました。 なお、このDockerイメージはShellスクリプト内でdocker runするときに自動で指定されるためます。加えて、イメージ内にSATySFiパッケージを含んでいるので.package-envと.satysfi-packagesに変更があった場合は必ずこのコマンドでイメージを生成しなおしてください。 Step6:main.satyファイルの編集 さて、ソースファイルの$mainSrcFileNameを編集していきます。 今回は初期状態(SATySFiのデモファイル)とは違うことが分かればいいので、タイトルにSampleをつける程度の編集でとどめておきます。 Step7:PDFの書き出し 先ほどコマンドを叩いたように次のコマンドを叩きます。 このときパスなどの問題が発生しないようにするために、Linuxのファイルパス形式でパスが扱えてなおかつbashコマンドが機能するターミナルでコマンドを叩いてください。 ./cmd/build-main.sh 問題なければ\$mainPdfFileNameという名前でPDFファイルが出来上がります。 $mainSrcFileNameの編集結果が正しく反映されていることがわかります。 まとめ 今回はSATySFiをインストールせずに利用するために、Dockerを使ったテンプレートを作ったので紹介しました。問題や修正点があればissueやPRをお願いします。 このテンプレートで利用できるコマンドにはDockerイメージの作成やPDF作成だけでなく、ほかにもいくつか便利なコマンドも用意してあります。詳しくはREADMEを確認してください。 このテンプレートでSATySFiがより簡単に扱えるようになり、SATySFiを扱える人が増えると幸いです。 Windowsのターミナルでbashやwslと叩いてログイン中のターミナルが切り替われば少なくとも切り替わった先ではBashは使えるはずです。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Terraform cloud agent を Cisco L3 Switch にインストして社内インフラをIaC

はじめに この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2021 (一枚目) の 5日目として投稿しています。 2017年版: https://qiita.com/advent-calendar/2017/cisco 2018年版: https://qiita.com/advent-calendar/2018/cisco 2019年版: https://qiita.com/advent-calendar/2019/cisco 2020年版: https://qiita.com/advent-calendar/2020/cisco 2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2 2021年版: https://qiita.com/advent-calendar/2021/cisco <=== ここ 2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2 延べ50名!有志すごい! これはなに? みんな大好きTerraformのマネージドサービスであるTerraform cloud Terraform cloudの Docker Agent を Cisco Catalyst9300 のApp-hosting機能でインスト ファイアウォール内にあるキャンパスコントローラーである Cisco DNA Center や認証ポリシーサーバーである Cisco Identy Services Engine (ISE) の設定(一部)をTerraform cloud経由で管理する例 Terraform cloudのトリガーは動作確認のためコマンド ※一般的な Docker エージェントをCiscoのLAN向け固定構成型フラッグシップスイッチであるCatalyst 9300にインストールして設定して動作確認する仕方の参考にもなれば幸いです。 構成 デモ デモの録画をキャプション付けて公開しました。(音が出ますのでご注意ください!) ※直リンクはこちらです。 動画のタイムライン 0:15 Catalyst9300の設定など 1:00 TFコンソールでCat9300上のAgentを確認 1:40 設定変更前のISEの内部IDの確認 1:50 設定変更前のDNACでのサイト設定の確認 2:06 社内へのVPNを切断 2:25 Terraformの設定を確認 2:39 Terraformの設定を確認(ISE) 2:55 Terraformの設定を確認(DNAC) 3:13 Terraform applyを実行 3:30 Terraform cloud上で実行状況の確認 4:45 ISEにIDを作成しているログをTerraformで確認 4:55 DNACにサイトを追加しているログをTerraformで確認 5:31 DNACとISEの設定を確認するためVPN接続 6:10 DNACに新たにサイトが追加されていることを確認 6:15 ISEに新たにIDが追加されていることを確認 設定 さっそく設定をみていきます。 1. Terraform cloud Terraform cloudにサインアップして、OrganizationおよびWorkspaceを作ります。今回は検証用に発行していただいたライセンスを利用しました。もし興味がありましたら、HashiCorpの担当者までコンタクトください? https://app.terraform.io/ ローカル環境(自分のデスクトップまたはサーバー)とterraform cloudを結びつけておきます。このあたりの流れはだいぶ省略しますが、興味ある方はググってください。 こちらのコマンドをローカルでうつといい感じにリダイレクトしてくれます。 terraform login または、手動でウェブコンソールから取得した自分のTokenを、以下のファイルとして書いておけば良さそうです。 $ cat ~/.terraform.d/credentials.tfrc.json { "credentials": { "app.terraform.io": { "token": "<クラウドから取得した自分のトークン>" } } }% 2. Terraform cloud agent on Cisco L3スイッチ 現行のCisco L3スイッチであるCatalyst 9300のApp-hosting機能を利用します。 シスコが提供する以外のアプリケーションを載せるためには、専用のUSB接続のSSDが必要になります。IOS XE 17.6.1 を利用します。 cisco Cat9300TMT03W#sho inventory NAME: "c93xx Stack", DESCR: "c93xx Stack" PID: C9300-24P , VID: V02 , SN: FCW2240D0RY NAME: "Switch 1", DESCR: "C9300-24P" PID: C9300-24P , VID: V02 , SN: FCW2240D0RY NAME: "Switch 1 - Power Supply A", DESCR: "Switch 1 - Power Supply A" PID: PWR-C1-715WAC , VID: V03 , SN: LIT22372265 NAME: "usbflash1", DESCR: "usbflash1-1" <---これ PID: SSD-120G , VID: 3.10 , SN: STP230311VB Cat9300TMT03W# Cat9300TMT03W#sho ver | i IOSXE Cisco IOS Software [Bengaluru], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 17.6.1, RELEASE SOFTWARE (fc6) * 1 41 C9300-24P 17.06.01 CAT9K_IOSXE INSTALL terraform cloud agentのコンテナをdocker hubから取得し、Catalyst9300のapp-hosting機能を使うためにtarファイルにします。 mac $ docker pull hashicorp/tfc-agent Using default tag: latest latest: Pulling from hashicorp/tfc-agent <snip> $ docker save hashicorp/tfc-agent:latest -o tfc-agent.tar $ ls tfc-agent.tar <--- これ Terraformのサイトで、Agent用のTokenを作成しておきます。TFC_AGENT_TOKENを作ってメモしておきます。 show app-hosting resourceコマンドで、スイッチ上にホストするアプリケーションが使えるリソースが確認できます。今回の例では、既にguestshellコンテナが動いていますが、その隣にTerraform cloud agentを立ち上げることにします。 cisco Cat9300TMT03W#sh app-hosting resource CPU: Quota: 25(Percentage) Available: 22(Percentage) VCPU: Count: 2 Memory: Quota: 2048(MB) Available: 1792(MB) Storage space: Total: 112547(MB) Available: 100395(MB) Cat9300TMT03W# Cat9300TMT03W#sh app-hosting list App id State --------------------------------------------------------- guestshell RUNNING Cat9300TMT03W# Cisco IOS XEのコマンド例です。内部のSVI VLAN11が、物理ポートと内部のアプリケーション用仮想ポートに繋がっているイメージです。別の記事でも詳しく書いていますので、興味があればそちらも参照ください。 参考) Catalyst 9300 Docker 上で ThousandEyes Agent の起動と設定 cisco interface Vlan11 ip address 10.71.154.33 255.255.255.248 IOS XE コマンドの中に、Docker起動オプションとして先に取得したTFC_AGENT_TOKENを書きます。 cisco app-hosting appid tfc_agent app-vnic AppGigabitEthernet trunk vlan 11 guest-interface 0 guest-ipaddress 10.71.154.35 netmask 255.255.255.248 app-default-gateway 10.71.154.33 guest-interface 0 app-resource docker run-opts 1 "-e TFC_AGENT_TOKEN=<Terraformサイトで取得した値>" run-opts 2 "-e TFC_AGENT_NAME=Cat9300TMT03W hashicorp/tfc-agent" name-server0 64.104.14.184 さて、上の設定でアプリケーションホスティングの環境は整いました。次はコマンドでtfc-agent.tarをインストールします。以下の例では、ウェブサーバー上に置いたtfc-agent.tarを直接インストールしていますが、一度スイッチのフラッシュにコピーしておくとより安全でしょう。 cisco Cat9300TMT03W#app-hosting install appid tfc_agent package http://<ipaddr>/tfc-agent.tar Installing package 'http://<ipaddr>/tfc-agent.tar' for 'tfc_agent'. Use 'show app-hosting list' for progress. しばらく待つと、以下のようにログが出力され、デプロイ完了です。 cisco Cat9300TMT03W#sh app-hosting list Nov 30 2021 05:43:07.789 UTC: %IM-5-IOX_URL_COPY_MSG: Switch 1 R0/0: ioxman: URL Copy: Success to copy http://<ipaddr>/tfc-agent.tar to usbflash1:/apps/tfc-agent.tar. Nov 30 2021 05:43:19.006 UTC: %IM-6-INSTALL_MSG: Switch 1 R0/0: ioxman: app-hosting: Install succeeded: tfc_agent installed successfully Current state is DEPLOYEDApp id State --------------------------------------------------------- tfc_agent DEPLOYED <---ここ guestshell RUNNING Catalyst9300上でのコンテナのライフサイクルは以下の流れで管理されます。インストール後、明示的にアクティベート、スタートする必要があります。このあたりは マニュアルに詳しい記載があります。 install/uninstall <--> activate/deactivate <--> start/stop Cat9300TMT03W#app-hosting ? activate Application activate <--- 2. これ clear Clear console/aux connection connect Application connect data Application data deactivate Application deactivate <--- debug debug install Application install <--- 1. これ move Move File settings Application settings start Application start <--- 3. これ stop Application stop <--- uninstall Application uninstall <--- upgrade Application upgrade verification Application signature verification setting (global) 順番に、アクティベート、スタートします。 cisco Cat9300TMT03W#app-hosting activate appid tfc_agent tfc_agent activated successfully Current state is: ACTIVATED Cat9300TMT03W# Cat9300TMT03W#app-hosting start appid tfc_agent tfc_agent started successfully Current state is: RUNNING 無事に動作しはじめると、RUNNINGステータスになります。 cisco Cat9300TMT03W#show app-hosting list App id State --------------------------------------------------------- tfc_agent RUNNING <--- 無事に動き出しました? guestshell RUNNING Cat9300TMT03W# Terraformのコンソールでもエージェントがコンタクトしてきていることが確認できました。 参考までに、L3スイッチ内部でTerraform cloud agentが利用しているリソースや仮想ネットワークの設定を確認できます。このコマンドは Cisco IOS XE app-hostingを試す際には確認用によく使います。 cisco Cat9300TMT03W#show app-hosting detail appid tfc_agent App id : tfc_agent Owner : iox State : RUNNING Application Type : docker Name : hashicorp/tfc-agent Version : latest Description : Author : Path : usbflash1:/apps/tfc-agent.tar URL Path : http://<ipaddr>/tfc-agent.tar Activated profile name : default Resource reservation Memory : 409 MB Disk : 10 MB CPU : 1480 units CPU-percent : 20 % VCPU : 1 Platform resource profiles Profile Name CPU(unit) Memory(MB) Disk(MB) -------------------------------------------------------------- Attached devices Type Name Alias --------------------------------------------- serial/shell iox_console_shell serial0 serial/aux iox_console_aux serial1 serial/syslog iox_syslog serial2 serial/trace iox_trace serial3 Network interfaces --------------------------------------- eth0: MAC address : 52:54:dd:be:f6:18 IPv4 address : 10.71.154.35 IPv6 address : :: Network name : mgmt-bridge-v11 Docker ------ Run-time information Command : hashicorp/tfc-agent Entry-point : /home/tfc-agent/bin/tfc-agent Run options in use : -e TFC_AGENT_TOKEN=<your_token> -e TFC_AGENT_NAME=Cat9300TMT03W hashicorp/tfc-agent Package run options : Application health information Status : 0 Last probe error : Last probe output : Cat9300TMT03W# 3. Terraformの設定 Terraformの設定は最低限に抑えています。DNAC、ISEともにTerraform Providerが公開されていますので、設定内容に興味がある方はこの辺り(DNAC、ISE )を参照ください。 以下の三つのファイルをローカルで作成し、実行しています。 main.tf ... Terraform cloudへの接続と、DNACとISE用のProviderの読み込み ise.tf ... Cisco ISEに追加するID情報 dnac.tf ... Cisco DNACに追加するサイト情報 尚、クラウドを使わない場合だとterraform.tfvarsで変数を管理するのが普通だと思いますが、その辺りはクラウドに登録しておけるので不要です。 例)https://app.terraform.io/app/kikuta/workspaces/cisco-sollab-01/variables main.tf terraform { backend "remote" { organization = "kikuta" workspaces { name = "cisco-sollab-01" } } } terraform { required_providers { ciscoise = { source = "CiscoISE/ciscoise" version = "0.0.2-beta" } dnacenter = { source = "cisco-en-programmability/dnacenter" version = "0.0.3" } } } ISE: ネットワークで認証されるユーザーをISE内部DBに追加(例:Qiita999を追加) ise.tf variable "TF_VAR_ISE_username" { type = string } variable "TF_VAR_ISE_password" { type = string } variable "TF_VAR_ISE_URL" { type = string } provider "ciscoise" { username = var.TF_VAR_ISE_username password = var.TF_VAR_ISE_password base_url = var.TF_VAR_ISE_URL debug = "true" ssl_verify = "false" use_api_gateway = "false" use_csrf_token = "false" } resource "ciscoise_internal_user" "example_1" { provider = ciscoise item { change_password = "true" description = "Managed by terraform cloud" enabled = "true" enable_password = "QiitaisK00l!" password = "QiitaisK00l!" name = "Qiita999" first_name = "Kazumasa" last_name = "Ikuta" expiry_date_enabled = "false" email = "kikuta@cisco.com" } } data "ciscoise_internal_user" "response" { depends_on = [ ciscoise_internal_user.example_1 ] } output "ciscoise_internal_user_response" { value = data.ciscoise_internal_user.response } DNAC: DNACで管理される「サイト」を新たに追加(例:Aichiを追加) dnac.tf variable "TF_VAR_DNAC_username" { type = string } variable "TF_VAR_DNAC_password" { type = string } variable "TF_VAR_DNAC_URL" { type = string } provider "dnacenter" { username = var.TF_VAR_DNAC_username password = var.TF_VAR_DNAC_password base_url = var.TF_VAR_DNAC_URL debug = "true" ssl_verify = "false" } resource "dna_site" "area" { provider = dnacenter item { type = "area" name = "Aichi" parent_name = "Global" } } resource "dna_site" "building" { provider = dnacenter depends_on = [dna_site.area] item { type = "building" name = "Nishiki Park Bldg" parent_name = "Global/Aichi" address = "Nishiki, Nagoya, Aichi" latitude = 35.17328858432372 longitude = 136.90092843701123 } } resource "dna_site" "floor" { provider = dnacenter depends_on = [dna_site.building] item { type = "floor" name = "Floor 1" parent_name = "Global/Aichi/Nishiki Park Bldg" rf_model = "Free Space" height = 100.1 length = 100.2 width = 100.1 } } 動作確認 今回は、ローカル環境からコマンドでTerraform cloudをトリガーしていますが、Terraform cloudとGithubをつないで、DNACやISEの設定もGithubにまとめてしまうともっとIaCぽくなりますね。 terraform init terraform plan terraform apply -auto-approve 所感 企業ネットワーク基盤の設備(DNACやISE、およびそれらが管理するスイッチ、無線、ルーター類)はファイアウォール内にある前提です。境界内のエージェントとクラウドのトンネルを活用することで境界外部から境界内部の構成をコードで管理してみる、ということを強調したかったので、あえてDemo動画でも、VPNを切断したり接続したりするプロセスを入れています。 Terraformがルーターやスイッチを直接操作する、というのではなく、ネットワークコントローラー類(今回はDNACやISE)のAPIとやり取りし、コントローラー類がネットワーク装置とやり取りする、というアーキテクチャもきれいですね。 Terraformはパブリッククラウド管理では、ほぼデファクトの一つとして定着していますが、このように境界内部(LANやプライベートクラウド)でも使えるユースケースが普及していくと、境界内外を一貫した方法でIaCできる可能性があると感じました。今回のDemoは全体のほんの一部ですが、これにCisco ACI環境やパブリッククラウド環境を追加することは容易であり、マルチクラウド、ハイブリッドエンタープライズのIaCの一つの姿として、またCI/CDの基盤としても有効ではないでしょうか。 DNACやISEについては、まだまだTerraformで多くのことができるわけではないので、この辺りはProviderが強化されることを期待しつつ、他にも有効なユースケースがないか、他にもいい感じにTerraformが管理できる境界内管理ツールがないか、もう少し調べてみたいと思いました。 Catalyst9300にDockerアプリケーションを簡単に載せられることは大きな可能性がありますが、Terraform cloud agentはその一つだと思いました。他にも、「これ載せたら面白いよね?!」というアイデアや気づきがありましたら、ぜひコメントまたはDMいただけると嬉しいです! 2022年へのカウントダウン、シスコジャパン有志によるアドベントカレンダー、もうしばらくお楽しみください♪ここまで読んでいただきましてどうもありがとうございました。2022年も、どうぞよろしくお願い致します。 参考 Cisco製品関連 Cisco Catalyst 9300シリーズスイッチ Cisco DNA Center Cisco Identity Services Engine Programmability Configuration Guide, Cisco IOS XE Bengaluru 17.6.x Terraform Cloud および Terraform Provider関連 Terraform Cloud Terraform Provider for Cisco DNA Center terraform-provider-ciscoise Cisco EN Programmability Cisco ISE 免責事項 本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初学者にlinuxのroot環境をオンラインで提供したので備忘録

きっかけ ローカルコミュニティの初学者の方々に少しでもlinuxに触れてほしいという思いから、今回の行動に至りました。 また、ただ環境を提供するだけでなく、初学者がCUI環境に入りやすいように、web上で、ホームディレクトリのファイル一覧を見たり、ホームディレクトリにファイルをアップロードできるようにしました。 やり方 dockerでubuntuコンテナを立ち上げ、そのコンテナをsshで公開するというのを人数分できるようにします。 準備 準備として、同一ディレクトリに以下の2ファイルを用意します Dockerfile FROM ubuntu:20.04 RUN apt-get update -y && \ apt-get install -y tzdata RUN apt-get install -y curl && \ apt-get install -y openssh-server && \ apt-get install -y vim RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config RUN curl -L https://github.com/sgreben/http-file-server/releases/download/1.6.1/http-file-server_1.6.1_linux_x86_64.tar.gz | tar xz COPY start.sh / ENTRYPOINT ["/start.sh"] RUN sed....の部分で、rootアカウントにsshでログインするために、設定ファイルを書き換えています また、その下で、web上でファイルを閲覧・アップロードするためのツールをダウンロード・展開しています。 sh'start.sh #!/bin/sh echo root:$PASSWORD | chpasswd service ssh start ./http-file-server -uploads -q -r redirect /$WEB_ROOTER_PATH=/root exec tail -f /dev/null start.shではrootユーザーのパスワードの変更、sshの起動、http file serverの起動をしています。 一番下のコマンドについてはこちらを参考にさせていただきました↓ https://www.itmedia.co.jp/enterprise/articles/1602/17/news004.html ビルド 先ほどのディレクトリで以下のコマンドを実行します。 docker build -t serve . これで、serveイメージの完成です。 実際に動かす 実際に動かすには、上記で作ったイメージを利用したコンテナを人数分作らなければなりません。 その際、注意するのはポートフォワーディングのポートが被らないようにすることです。 また、ユーザーのホームディレクトリを安易に見られないように、WEB_ROOTER_PATHを十分ランダムなものに設定する必要があります。 理想としては、ホスト側でwebサーバーを前にかませて認証を設けるのが良いでしょう。 今回は一人に提供する前提のコンテナ化コマンドを記載します。 docker run -it -p 7000:22 -p 8000:8080 -e PASSWORD=1234 -e WEB_ROOTER_PATH=test -d --name servetest serve ※ 7000:22はsshのポートフォワーディング、8000:8080はhttp file serverのポートフォワーディングです。 ここまでくれば、あとはsshでlinux環境に入れますし、webからディレクトリを参照することもできます。 ※実際に複数人数分のコンテナを作る際は、7000、8000の部分をそれぞれ被らないように変更して、人数分のコンテナを作成します。また、必要に応じてsshでログインする際のPASSWORDも変更しましょう。※ ssh接続の例(host ipがlocalhostの場合) ssh -p 7000 root@localhost web接続の例(host ipがlocalhostの場合) http://localhost:8000/test --追記: ROOTERを設定したところで、リダイレクトされるので意味ないですね.....どうしましょう... 2021 12/5追記: -rオプションでリダイレクト先を存在しないディレクトリ(/redirect)にすることでとりあえず回避しました。 繰り返しになりますが、理想は直アクセスの前に認証を挟むのが良いです。 終わり とりあえずlinuxに気軽に触れてほしいという衝動で作成したので荒い部分もあると思いますが、おおむね満足のいくものができたのでよかったです。普通にOpenStack使うという手もありますが、諸事情で数日中に提供準備を整えたかったので、使用したことのあるdockerで構築しました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む