Docker – PostgreSQL

イメージ取得とコンテナ作成

PostgreSQLのイメージを取得。

イメージの確認。

コンテナ作成と実行。ここで、ホスト側で既にPostgreSQLが動いているので、ホスト側のポートを5431に設定している。

動作確認

ターミナルに入る。

PostgreSQLのターミナルに入る。

データベースの確認。

テーブル作成。

作成されたテーブルを確認。

レコード操作確認。

なお、今のマシンにはWindows版のPostgreSQLもインストールしているので、直接コンソールからpsqlも使える。ただしバージョンがコンテナ上のサーバーとWindows上のpsqlで異なるので警告が出る。

タイムゾーン

タイムゾーンを確認するとUTCになっている。

Docker Composeでタイムゾーンを設定するには、以下の様に環境変数をセットする。

 

Docker – PHP/Apache

手動でインストール

DockerのUbuntu+Apache環境にPHPをインストールする。

インストール中、タイムゾーンの選択を求められる。

インストール完了後、apache2をリスタート。

このあと/var/www/htmlに以下のような内容でphpinfo.phpファイルを作成。

ブラウザーからlocalhost:8080/phpinfo.phpにアクセスして以下のような内容を確認。

  • タイムゾーンはOSでAsia/Tokyoにしたが、PHPではUTCになっている
  • php.iniの場所が確認できる(/etc/php/8.1/apache2/php.ini)

DockerfileとComposeでインストール

手動でのインストールと同じ手順をDockerfileとComposeで管理する。

Dockerfileの内容は以下の通り。

  • aptでsystemctl, apache2, phpをインストール
  • apt-getでtzdataをインストール
  • /etc/timezoneに”Asia/Tokyo”を書き込む
  • dpkg-reconfigureでtzdataを再設定(noninteractiveで)

上記のDockerfileの内容でコンテナをビルド。

phpinfoのdateの項目中default timezoneがAsia/Tokyoになっているのが確認できる。

以下の内容でphp.iniをDokerfileと同じ場所に置き、DockerfileにADD ./php.ini /etc/php/8.1/apache2/php.iniを書くという方法も紹介されていたが、それがなくてもPHPのタイムゾーンは変更されていた。

ただしmbstringの方は今後設定が必要かもしれない。

 

Docker – タイムゾーン

概要

Docker~UbuntuでタイムゾーンをUTCJSTに変更した時の手順。

手動で設定

最初はUTC

タイムゾーンの設定なしにコンテナを起動するとUTCになっている。

この時点で/etc/timezoneファイルは存在しない。

tzdataのインストール

tzdataをインストール。タイムゾーンの選択は対話形式。

無事JSTに変更されている。

/etc/timezoneファイルが作成され、内容はAsia/Tokyoとなっている。

Dockerfile

tzdataのインストール

最初にtimedatectlのインストールを試みたが、エラーでインストールできなかった。そこでtzdataをインストールする。

ENVで非インタラクティブモードに設定するのが定石らしい。

正常終了するが、UTCのまま。

/etc/timezoneは作成されていて、内容はEtc/UTCになっている。

/etc/timezoneの書き換えによる設定

Dockerfileを編集して、Asia/Tokyoの設定を追加する。

dateコマンドではJSTになっているのが確認できる。

ただし、/etc/timezoneの内容はEtc/AsiaではなくEtc/UTCのまま(echoが効いていない?)。

また、/etc/localtimeはEtc/UTCへのシンボリックリンクが張られている。

この方法は、システムのローカルタイムはJSTになっているものの、/etc/timezone、/etc/localtimeともUTCのままなのが気になる。

/etc/localtimeへのシンボリックによる設定

Dockerfileを以下のように変更して試してみた。

dateコマンドではJST、/etc/timezoneはEtc/UTCで、/etc/localtimeはAsia/Tokyoへのシンボリックリンクとなっていた。

この方法では、システムのローカルタイムはJSTとなり、/etc/timezoneはUTCのままだが、/etc/localtimeはAsia/Tokyoとなった。

 

Docker – バインド

概要

Dockerのホストとコンテナでディレクトリーをバインドして共有する。runコマンドの--mountオプションを使う。

以下を前提とする。

  • UbuntuにApache2をインストールしたイメージ(ubuntu-apache)を使う
  • 以下のフォルダーとディレクトリーをバインドする。
    • ホスト側:C:\dev\docker\ubuntu\share
    • コンテナ側:/var/www/html

mountオプション

runコマンドのmountオプションの書き方は以下の通り。key=valueの間のコンマの前後にスペースを入れないこと。

--mount type=bind,src=[ホスト側],dst=[コンテナ側]

実行例

イメージを確認。

runコマンドを実行。

これにより、ホスト側のC:\dockshareフォルダーの内容とコンテナ側の/usr/local/shareディレクトリーの内容が同期される。

コンテナ側の上書き

コンテナが起動したとき、ホスト側のフォルダーの内容でコンテナ側のディレクトリーが上書きされる(ホスト側のフォルダーが空ならコンテナ側にファイルがあったとしても空になる)。ホスト側のC:\dev\docker\ubuntu\shareが空だとコンテナ側の/var/www/htmlディレクトリーも空になり、デフォルトページindex.htmlも削除される。

ここでホスト側の共有フォルダーに新たなindex.htmlを作ると、その内容がコンテナ側に反映され、localhost:8080で表示できる。

なお共有後はコンテナ側での作成・削除・変更内容もホスト側に反映される。

 

Docker – Apache

手動で構築

コンテナの起動

Ubuntuのコンテナ内で、手動でApache環境を構築する。

まずUbuntuのコンテナを起動する。その際、ホスト側のポート8080とコンテナ側のポート80をバインドしておく。

UbuntuのBash環境に入る。まだ/varディレクトリー下にwwwディレクトリーはない。

インストール

まずapt update

systemctlをインストール。

次にapache2をインストール。

/var/wwwディレクトリーが作成され、その下のhtmlディレクトリー内にindex.htmlが作られている。

Apche2起動

systemctlでApache2の稼働状況を確認し、起動させる。

ここでブラウザーからlocalhost:8080にアクセスすると、Apache2のデフォルトページが表示される。

Dockerfileでイメージ生成

Dockerfileに記述した内容で、指定した構成のイメージを作成することができる。ここではUbuntuのイメージをベースに、Apache2をインストールして実行させるイメージを作成する。

まず、Dockerfileを以下の内容で作成する。

  • FROMでベースとなる既存のイメージを指定
  • RUNで実行開始後にaptをupdateし、systemctlとapache2をインストール
  • CMDでsystemctlを実行させ、apache2を起動する
  • ホストとコンテナのポートのバインディングは、コンテナ起動時に指定する

Dockerfileがあるディレクトリーでbuildを実行。

docker build [Dockerfileの場所] -t [コンテナ名]

Dockerfileと同じディレクトリーでこれを実行しているので、Dockerfileの場所は'./'。何度か同じ操作を繰り返しているのでキャッシュが使われていてメッセージはシンプル。

作成されたイメージを確認。

コンテナ名、ポート番号のバインディングなどを指定してrunを実行。

この状態でブラウザーからlocalhost:8080にアクセスすると、Apache2のデフォルトページが表示される。

Docker Composeで起動

コンテナを起動するのに、毎回コマンドラインでコンテナ名を指定したりポートをバインドするのではなく、Docker Composeを使って事前に定めておく。

本来Composeは複数のコンテナを連携させるのに使われるが、単一のコンテナの起動設定にも使える。

まずDockerfileと同じ場所に以下の内容でdocker-compose.ymlファイルを作成する。

そしてdocker-composeを実行。その際、デーモンで実行させるため-dオプションをつける。

この状態でバインドされたホスト側のディレクトリーにindex.htmlを作ったり変更すると、localhost:8080にアクセスしてその内容が確認できる。

 

Docker – Ubuntu

Ubuntuを使う

最新版の取得と実行

イメージ取得。タグ指定を省略して単にubuntuとするとlatestが取得される。

取得したイメージ。

コンテナ実行

コンテナ生成

オプションは以下のとおり。

  • -itオプションは-i-tの組み合わせで、コンソール入出力をコンテナの入出力とするためのオプション
  • -dはデーモンで、コマンド実行後もコンテナが動作し続けるよう指定。
  • これらをまとめて-itdと指定してもよい

runコマンドはコンテナの生成と実行を一度に行うが、これをcreatestartに分けてもよい。createコマンドでは-dオプションは指定できない。生成されたコンテナをstartコマンドで実行開始する。

コンテナの実行を確認。

Bash実行

Dockerのexecコマンドで実行中のコンテナ内でコマンドを実行

実行確認。

OSのバージョン確認。

ログアウト。

コンテナ停止

stopでコンテナを停止させる。

バージョンを指定した取得と実行

この時点で最新のLTSは22.04.3だが、22.04のバージョンをタグで指定して取得してみる。

イメージ確認。

コンテナ実行。

Ubuntuのバージョン確認。

 

Docker – コマンド

確認・検索系

version: バージョン確認

search:イメージ検索

Docker Hub上のイメージを検索する。

オプション

--limit N:検索個数の上限(デフォルトは25)

images:イメージ一覧

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

ps:コンテナ一覧

コンテナの一覧を表示する。

デフォルトでは実行中のコンテナのみ表示するが、-aオプションで停止中のコンテナも含めて表示される。

イメージ管理

search:イメージ検索

指定した語が含まれるイメージを検索する。

pull:イメージ取得

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

build:イメージ構築

Dockerfileの内容に従ってイメージを構築する。

docker build [Dockerfileの場所] -t [イメージ名]

rmi:イメージ削除

取得済みのイメージを削除。

コンテナ管理

create:コンテナ生成

イメージからコンテナを生成して実行可能な状態にする。-dオプションは指定できない。

docker create --name [コンテナ名] [イメージ]

start:コンテナ実行

既に存在するコンテナを実行

start [オプション] [イメージ]

指定できるオプションは-a-iのみ。

run:コンテナ生成・実行

実行するたびに新たなコンテナが生成・追加されて実行される。

オプション

  • -d:デーモンで実行
  • -it:コマンドラインで対話的な操作を可能にする(--interactive--ttyの2つのオプションを短縮形で同時指定)
  • --name:コンテナのNAMEを指定(指定しないとDocker側で適当に付与される)
  • -p:ポートのバインディング(-p [ホスト側ポート]:[コンテナ側ポート]

stop:コンテナ停止

実行中のコンテナを停止

exec:実行中コンテナのコマンド実行

たとえばLinux系でシェルを実行させるなど。

docker exec -it [コンテナ名] /bin/bash

rm:コンテナ削除

コンテナを削除。

Compose

compose:Docker Composeでコンテナを作成・起動

予め作成したymlファイルに従ってコンテナを作成し、起動する。

docker compose up -d

 

Docker – インストールほか

インストール

インストール開始

  1. Get Dockerからインストーラーをダウンロード
  2. インストーラーを実行
  3. 再起動
    • サブスクリプション同意のダイアログ
    • 無償条件は小規模事業(従業員250人未満かつ年間収益1,000万ドル未満)、個人利用、教育、非商用オープンソースプロジェクト)
    • 個人利用ならキャンセル

WSLでエラー

インストール中にWSL (Windows Subsystem for Linux)のバージョンが低すぎるとエラーになった。

docker_error_installation_wsl

WSLをアップデート。

再起動。

Docker Desktop起動

WindowsのアプリケーションからDocker Desktopを起動後、コンソールでバージョンを確認。

イメージやコンテナは空っぽの状態。

Learning Center

Welcome

Docker DesktopのLearning centerを試してみる。まずWelcomeをGitHubからクローン。

得られたフォルダー。

ターゲットのフォルダーに移動してビルド。welcomeの画面が表示される。

multi-container-app

GitHubからクローン。

フォルダー構成。

compose.ymlの内容。

compose実行。

localhost:3000にアクセスして結果確認。

Persisting Data

GitHubからクローン後、compose.ymlを確認。

compose実行。

これでコンテナーを停止/削除してもデータが保存される。なお、volumeの実体の保存場所はWindowsの場合以下の場所で、エクスプローラーのアドレスバーに\\wsl$と入力してたどっていける。

 

Atom – VagrantにSFTP接続

概要

  • RemoteFTPパッケージを利用
  • VagrantのSSHの設定内容を確認
  • Atomの.ftpconfigを編集
  • 接続

VagrantのSSH設定内容確認

vagrant upの前の状態で、Vagrantfileのあるディレクトリー下でvagrant ssh-configを実行。

.ftpconfigの編集

Atomを起動、Packages→RemoteFTP→ToggleでサイドパネルにRemoteタブを表示。Edit Configurationで.ftpconfigを表示させて編集。

 

接続開始と終了

サイドパネルのConnectを実行して接続。終了時はPackages→RemoteFTP→Disconnect。

 

 

コイル(インダクター)

電流・磁界の法則

右ネジの法則

電流が流れると、その方向に対して右回りの磁界が発生する(Maxwell’s right-handed screw rule)。

右手の法則

コイルに電流を流すと、電流の向きが右手を握った各指の方向のとき親指の挿す方向に磁界が発生する。

フレミングの左手/右手の法則

絵は面倒なので割愛。人差し指が磁界、中指が電流、親指が力の方向。左手は磁界内の電流に働く力、右手は磁界内で運動する場合に発生する電流の方向。

ローレンツ力

電荷e[C]の荷電粒子が磁束密度B[T]内を運動ベクトルvで移動するとき、荷電粒子に対してフレミングの左手の法則に従って力が働く。

このとき、vが磁束に対してなす角をθとすると、荷電粒子に働く力は以下の様になる。

(1)    \begin{equation*} f = q v (\sin \theta) B \end{equation*}

ローレンツ力の方向まで含める場合、ベクトルの外積よって以下の様に表せる。

(2)    \begin{equation*} \boldsymbol{f} = q \boldsymbol{v} \times \boldsymbol{B} \end{equation*}

レンツの法則

コイルを通る磁束が変化するとき、その磁束の変化を妨げる方向に誘導電流が生じる。

たとえば以下の図では、コイルに対して磁石のN極側を近づけている。このときコイルに対して左から右へ向かう磁束が増加するので、それ打ち消す右から左の磁束を増やすように誘導電流が流れる。

この状態で磁石が離れていくときは右向きの磁束が減少するので、コイル内で同じ右向きの磁束を発生させるよう、上図と逆向きの電流が流れる。

一方、S極が近づくときは左向きの磁束が増えるので、これと逆の右向きの磁束が発生するよう、上図と逆向きの電流が流れる。

S極が離れる場合には、左向きの磁束が減少するので、これを補うように左向きの磁束を発生させる方向(上図と同じ方向)に電流が流れる。

ファラデーの法則

閉回路を貫く磁束Φが変化するとき、レンツの法則によりその変化を妨げる方向の電流が流れるが、この起電力を誘導起電力という。誘導起電力の大きさは以下のように表される。

(3)    \begin{equation*} | V | = \left| \frac{d \Phi}{dt} \right| \end{equation*}

起電力の正負の向きについて、「磁束の変化を妨げるように」というレンツの法則から、以下の様に表現される。

(4)    \begin{equation*} V = - \frac{d \Phi}{dt} \end{equation*}

またコイルの巻き数がNのときは、以下の様になる。

(5)    \begin{equation*} V = - N \frac{d \Phi}{dt} \end{equation*}

コイルの自己誘導

自己誘導とは

コイルにかかる電圧が変化した場合場合、電流の変化に応じて磁界が変化するが、レンツの法則によってそれを阻止しようとする方向の電流を流そうという起電力も生じる。このような現象をコイルの自己誘導と言い、自己誘導によって生じる元の電圧と逆の起電力を逆起電力という。

電源が立ち上がった場合

たとえば以下のような回路を考える。ここで電源電圧が0→Eに立ち上がった場合、コイルによる逆起電力、抵抗による電圧降下が生じる。電源の起電力は正極側を⊕としている。抵抗Rの電圧は電源に対して電圧降下となる電流の向きの矢印、コイルの方は電流の変化によるので両方向きの矢印としている。

電流をII(t)として、電圧のバランスを定式化すると、以下のようになる。

(6)    \begin{equation*} E - L \frac{dI}{dt} - RI = 0 \end{equation*}

この微分方程式を以下のように解いていく。

(7)    \begin{equation*} \frac{dI}{E - RI} = \frac{dt}{L} \end{equation*}

(8)    \begin{equation*} -\frac{1}{R} \ln (E - RI) = \frac{t}{L} + const \end{equation*}

(9)    \begin{equation*} I = \frac{E - k e^{- \frac{R}{L} t}}{R} \end{equation*}

ここでIt=0 = 0の条件によりkを決定する。

(10)    \begin{equation*} \frac{E - k}{R} = 0 \quad \Rightarrow \quad k = E \end{equation*}

よって、自己誘導を含めた電流変化は以下のように求められる。

(11)    \begin{equation*} I = \frac{E}{R} \left(1 - e^{- \frac{R}{L} t} \right) \end{equation*}

以下のグラフは、L = 100mH、R = 1kΩ、E = 5Vの場合にスイッチON以降の電流変化を計算したもの。自己誘導の影響がなくなり定常電圧になるのに500μsほどかかっている。

電圧が立ち下がった場合

初期電流It=0 = E/Rとして、t = 0でE = 0になったとして先の微分方程式を解いてみる。まず式(6)でE = 0と置く

(12)    \begin{equation*} - L \frac{dI}{dt} - RI = 0 \end{equation*}

これを解いて

(13)    \begin{equation*} I = k e^{- \frac{R}{L} t} \end{equation*}

初期条件を考慮して以下を得る。

(14)    \begin{equation*} I = \frac{E}{R} e^{- \frac{R}{L} t} \end{equation*}

この式形は式(11)と上下逆の形になっていて、以下のようなグラフになる。

サージ

サージの考え方?

コイルを含む回路を半導体素子で開閉した場合、スイッチOFFの際に高電圧のサージが発生するということを知った。ただし定性的な(あるいは感覚的な)原理は多くみられるが、そのメカニズムがどうも腹に落ちない。

「スイッチOFFにしても電流が流れようとするので誘導起電力が発生し・・・」という説明を見かけるが、もし理想的なスイッチで瞬間的にOFFとなるなら、誘導電流が流れる時間がゼロだから、回路としてはそのまま黙ってしまうのではないか(dI/dtが無限大になるのとどう関係するのか定かではないが)。

スイッチが完全にOFFになるまでに若干のスパークが発生することや、スイッチング阻止の抵抗が無限大ではないことを含めて説明している場合もあり、これは現実論として納得できる。

特にこちらのサイトはとても参考になったので、これを自分なりにトレースして、理解を試みた。

まず以下の図で、電源Eに接続していた状態からスイッチを抵抗S側に切り替えたとする。ただし以下の点に留意する。

  • 切り替え前は定常状態で、回路の電流はI = E/R
  • ここでのスイッチは理想的なスイッチとし、抵抗Sが現実のスイッチ切り替え時の抵抗に相当

ここで切り替えの瞬間をt = 0として微分方程式は以下のようになる。

(15)    \begin{equation*} - L \frac{dI}{dt} - RI - SI = 0 \end{equation*}

初期条件t = 0でI = E/Rとして解いて、以下を得る。

(16)    \begin{equation*} I = \frac{E}{R} e^{- \frac{R + S}{L}t} \end{equation*}

この電流に対してコイルは起電側となり、2つの抵抗で電圧降下となって、それらは以下のようになる。

(17)    \begin{equation*} \left\{ \begin{array}{l} V_R = RI = E e^{- \frac{R + S}{L}t} \\ V_S = SI = \dfrac{S}{R} E e^{- \frac{R + S}{L}t} \\ V_L = - L \dfrac{dI}{dt} = - \dfrac{R + S}{R} E e^{- \frac{R + S}{L}t} \end{array} \end{equation*}

この式によるなら、t=0でコイルによる起電力は(R + S)/Rとなり、このうちS/Rが抵抗Sの電圧降下となる。たとえばR=1kΩのときにSが10kΩでも元の電源電圧の10倍の電圧がSの両端にかかることになる。

この様子を先と同じ条件L = 100mH、R = 1kΩ、E = 5Vに加えてS = 10kΩとして描いたのが以下のグラフ。スイッチOFFのときにEの10倍の50Vが生じ、そこから急激に電圧が下がっている。また時定数(R + S)/Rも大きくなるので、減少の時間も1オーダー短くなっている。

このSが大きくなると、その倍率に応じて大きな電圧が生じ、低減時間は短くなる。すなわち、一瞬の間だけ高電圧が発生する。これがコイルによるサージと呼ばれるものではないか。

ただし元々接続されていたRの両端の電圧の最大値は変わらないので、サージの影響を受けるのはスイッチ素子ということになる。ここにトランジスターなどを使っていると、たとえばCE間に逆向きの高電圧がかかって破壊されてしまう。

保護回路

コイルサージから回路を保護するためにいろいろあるようだが、最も簡単なのは以下の様にダイオードを加えることらしい。

通常のスイッチONの状態ではダイオードが逆向きなのでコイルに電流が流れ、サージ電流はダイオードを通じて戻るので、RSには影響を与えない。