それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

LXC 内部で docker を動かす。 ( docker in LXC container )

LXC 内部で docker を動かす。

既知の問題点 lxc 内部で docker は動かない ことがある

調べた結果、次の条件で動かない。

  • docker のoverlay2 が lxc デフォルトzfs で動かない
  • docker のoverlayがありlxc 内部でsnapcraft-docker を使うと動かない。
  • docker の権限管理がLXC のデフォルトで動かない。

今の処分っている問題点は、overlay2 の関するものなので、zfs を避けると動く

ただし、snapcraft で docker を入れると動かない。 snap でインストールされる docker のバージョンの問題なのか、 snap が管理するストレージがネストしててやばいのか。

そのへんはまだよくわかってない

ということで docker in LXC のポイント

  • snapcraft の docker は動かない
  • lxc の特権コンテナが必要
  • LXCストレージでZFSでDockerは動かない

このポイントをクリアすると動作しました。

こうすればひとまず動く

btrfs のストレージを作る。

lxc storage create bt01 btrfs

docker を動かすLXCコンテナを ubuntu のLTSから作る

lxc launch ubuntu:20.04 docker-host --storage bt01

LXCのコンテナに対していくつかの権限設定をする。

lxc config set docker-host security.privileged true
lxc config set docker-host security.nesting true

新しい権限で、LXC コンテナを起動し直す。

lxc restart docker-host

Ubuntu LTS のコンテナに対して apt 更新を掛ける。

lxc exec docker-host apt update 
lxc exec docker-host apt upgrade  

これでbtrfs で作ったストレージにコンテナを立ち上げたので、その内部で docker をインストールしてみる

lxc exec docker-host apt install docker.io

インストールした docker で hello-world をしてみる。

lxc exec docker-host docker run hello-world

やったね、無事にrun docker in LXC container ができたよ。

docker run hello-world を試す。

lxc exec 経由で docker run を試す。

lxc exec docker-host docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9
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/

無事に動いたときの設定などをメモっておく

LXC ホスト

takuya@:~$ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:    focal

LXD バージョン

takuya@:~$ lxc version
Client version: 4.3
Server version: 4.3

LXC コンテナ

takuya@:~$ lxc exec docker-host -- lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:    focal

Docker バージョン

takuya@:~$ lxc exec docker-host docker version
Client:
Version:           19.03.8
API version:       1.40
Go version:        go1.13.8
Git commit:        afacb8b7f0
Built:             Tue Jun 23 22:26:12 2020
OS/Arch:           linux/amd64
Experimental:      false

Server:
Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.8
  Git commit:       afacb8b7f0
  Built:            Thu Jun 18 08:26:54 2020
  OS/Arch:          linux/amd64
  Experimental:     false
containerd:
  Version:          1.3.3-0ubuntu2
  GitCommit:
runc:
  Version:          spec: 1.0.1-dev
  GitCommit:
docker-init:
  Version:          0.18.0
  GitCommit:

2023-10-06 追記

docker compose で mailcow を上記の状態で up down したら

などとなり、OS起動時は動くのに、docker 側で down -> up するとエラーになった。

Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write "a *:* rwm": write /sys/fs/cgroup/devices/docker/3cf0487fa80fd2a06f4a61b7c5ae58231db463e2a922bd28ca4a7abb00247b18/devices.allow: operation not permitted: unknown

なんとなく、以前のdocker on lxc で使っていた raw.lxc を書き直したらエラーが出なくなった。

  raw.lxc: |-
    lxc.mount.auto=proc:rw sys:rw cgroup:rw
    lxc.cgroup.devices.allow=a
    lxc.cap.drop=

ailed to write "a : rwm": write /sys/fs/cgroup/devices/docker

devices.allow … operation not permitted` in privileged container

Cannot start hello-world in LXC conatiner

なんでLXCコンテナの中でDockerを動かすのか。

特に理由はない。なんか面白そうだから。

強いてあげるなら、docker / docker-compose したコンテナを長期間動かすと、メンテがめんどくさいから。

docker/docker-compose を使ってると、コンテナが増えすぎてどのコンテナがどのサービス用なのかゴチャゴチャになってわからなくなる。巷ではdocker の管理UIをdocker run すとかもあるみたいだけど、それもなんか違う気がするし、docker のコンテナとボリュームが稼働しているマシンを別のマシンに移動させたり、バックアップを取得したり、そういう管理が本当にめんどくさい。

docker ってパパっとインスタンスを立ち上げて使い捨てるには本当に便利なんだけど、長期間動かすのには向いてない気がする。ちょっとパフォーマンスが足りないからCPUやメモリを潤沢にした新サーバーに移動しようとか、さくらのVPSの別の契約に移動しようとか、そういうことをやろうとして本当に苦労した。なのでdocker を、LXCとかlibvirt+kvm に閉じ込めておくほうがライブマイグレーションができて便利だと思った次第。

docker は開発用に実験環境を作るのは本当にすばらしい。docker でインスタンスをサクッと立ち上げるのもスラバシイし、デプロイ時にデータボリュームとソースコードの領域を分けられるのも素晴らしいと思うんだけど、データボリュームをいちいち移動するのとか、デプロイ設定を書き換えるのが面倒じゃないですかね。まぁGoogleAmazonを使えばいいんだろうけど。

LXC/LXDとかsystemd-nspawn とか名前空間を使った実行に docker が対応すべきだと思います。はい。個人的な意見ですけど。

個人的な意見ですけど、docker はソフトウェア開発の環境にすごく向いている。LXC はサーバーの実験環境をつくるのにすごく向いている。と思います。

そもそも docker run したインスタンスを長期間運用するとなると、バージョンアップとかコンテナのベースになってるイメージの更新とかあるので、dockerfile だとか docker-compose をよーく読んでvolume をよく考えないといけない。その作業がもうめんどくさい。

nextcloud や mattermost や gitlab をdocker で起動して痛い目にあった

LXC のコマンドで基本操作 / lxc でイメージ検索とインストール / centosとubuntu

LXC のイメージについて。

LXDは仮想マシンの「統合管理」的なものなので 、docker のようなコンテナ、vbox のような仮想マシン、この2つを管理できる。コンテナは lxc のコンテナ、インスタンスqemu仮想マシンを扱えるようですね。

docker と違って lxc で起動すると、systemd がはじめから起動しているので、docker より扱いやすいです。

docker のようにストレージをレイヤ管理しないし、より「普通の仮想マシン」にちかいので、長期間運用するようなホストに向いていると思います。

「systemd が動いてる docker 」がほしいと思った方は lxc を選ぶと幸せになれるでしょう。

LXC のコマンド

LXC / lxd のコマンドは、現在は、lxc のコマンドとサブコマンドに統合されています。

lxc list 仮想マシン・コンテナの一覧

lxc list 

LXCで新規作成と終了と削除

新規作成

lxc launch ubuntu:18.04 myFirstContainer

このコマンドは、次のようになってる

lxc launch イメージ名 自分で決めるホスト名

停止・再起動・開始

lxc stop myFirstContainer
lxc restart myFirstContainer
lxc stop myFirstContainer

削除

削除は、停止後に出来ます。

lxc delete  myFirst

コンテナ環境内に入る

コンテナの中に入るには docker と変わりません。

lxc exec myFirst bash 

exec で任意のコマンドを実行できる。

lxc exec myFirst sh
lxc exec myFirst login
lxc exec myFirst systemctl status  sshd
lxc exec myFirst systemctl status nginx

イメージの検索について

LXDにビルトインされているイメージ用リモートサーバーの名前空間は、ubuntu のlxc では、次の3つです。

ubuntu:
ubunt-daily:
images:

取得済みのイメージ

lxc image list 

公式イメージ

取得済みのイメージと引数が違うだけなのでちょっと覚えづらい

lxc image list images:
lxc image list ubuntu:

イメージの一覧を見る時に使うコマンドの例

lxc image list images: 'debian'
lxc image list images: 'debian/11/amd64'
lxc image list images: 'centos'

検索イメージは多くなると 見づらいので grep するといい

lxc image  list  ubuntu: | grep 20.04
lxc image  list  images: | grep debian

さらに詳細を見たいときは次のようなオプションを使う

lxc image list images: 'debian/11/amd64' -c Lfpdatsu

イメージサーバーはどこにあるのかというと https://images.linuxcontainers.org/ をみると、全部見ることができるけど多すぎて見ることはないんじゃないかと。

debian を起動する場合

lxc image list images: debian

新規で起動するなら次のようにする

lxc launch images:debian/10

デフォルトで、最新版とCPUアーキテクチャ(amd64)と、コンテナが選ばれて起動します。

centos を起動する場合

CentOS を起動するときは次のようにする。

images:XXX の images:を付けるのが重要

lxc launch images:centos/8 

ubuntu 以外は名前空間が違うので注意

ubuntu 以外のイメージを使うときは、images:XXX の images:を付けるのが重要

lxc launch ubuntu:18.04 ubuntu1804
lxc launch images:debian/10
lxc launch images:centos/8 --storage bt01

ubuntu だけは、ubuntu を先頭につけるのですが、ubuntu:18.04 でインストールできるからといって debian:10 でインストールできるわけではありません。最初のうちはよく間違うので注意。

ubuntus: と images:という : セミコロンが配布サーバを指定する名前空間だと思って置くとベター。

centos を検索するといっぱいあります

grep すると長いので、ある程度わかっていたら、名前を入れたほうが速い。

takuya@:~$ lxc image list images:centos
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
|              ALIAS               | FINGERPRINT  | PUBLIC |               DESCRIPTION                | ARCHITECTURE |      TYPE       |   SIZE   |          UPLOAD DATE          |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/6 (3 more)                | 047d1e4bbd22 | yes    | Centos 6 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 75.83MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/6/cloud (1 more)          | 1f2c57f63c95 | yes    | Centos 6 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 84.13MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/6/cloud/i386              | 50fb77c012f1 | yes    | Centos 6 i386 (20200714_07:08)           | i686         | CONTAINER       | 84.26MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/6/i386 (1 more)           | dd5ca34a8695 | yes    | Centos 6 i386 (20200714_07:08)           | i686         | CONTAINER       | 75.96MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7 (3 more)                | a007f18afb7c | yes    | Centos 7 amd64 (20200714_07:08)          | x86_64       | VIRTUAL-MACHINE | 417.25MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7 (3 more)                | eeecaeac13c8 | yes    | Centos 7 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 83.16MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/armhf (1 more)          | b8a283e1740c | yes    | Centos 7 armhf (20200714_07:08)          | armv7l       | CONTAINER       | 78.95MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/cloud (1 more)          | 89fee0193ddd | yes    | Centos 7 amd64 (20200714_07:08)          | x86_64       | VIRTUAL-MACHINE | 420.13MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/cloud (1 more)          | b3b9407c1839 | yes    | Centos 7 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 89.75MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/cloud/armhf             | 483310afd026 | yes    | Centos 7 armhf (20200714_08:11)          | armv7l       | CONTAINER       | 85.35MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/cloud/i386              | 3b176216218d | yes    | Centos 7 i386 (20200714_07:08)           | i686         | CONTAINER       | 90.55MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/7/i386 (1 more)           | 34ebc449e97f | yes    | Centos 7 i386 (20200714_07:08)           | i686         | CONTAINER       | 83.72MB  | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8 (3 more)                | 3c980b7f2b1d | yes    | Centos 8 amd64 (20200714_07:08)          | x86_64       | VIRTUAL-MACHINE | 472.31MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8 (3 more)                | 25188125674b | yes    | Centos 8 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 125.23MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream (3 more)         | 472c6fbd783d | yes    | Centos 8-Stream amd64 (20200714_07:08)   | x86_64       | VIRTUAL-MACHINE | 488.50MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream (3 more)         | fac6147bf59b | yes    | Centos 8-Stream amd64 (20200714_07:08)   | x86_64       | CONTAINER       | 136.46MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/arm64 (1 more)   | 914ae88a4981 | yes    | Centos 8-Stream arm64 (20200714_07:08)   | aarch64      | CONTAINER       | 132.72MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/cloud (1 more)   | 284967f0a5a9 | yes    | Centos 8-Stream amd64 (20200712_07:08)   | x86_64       | VIRTUAL-MACHINE | 511.88MB | Jul 12, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/cloud (1 more)   | eb677b861e46 | yes    | Centos 8-Stream amd64 (20200714_07:08)   | x86_64       | CONTAINER       | 151.26MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/cloud/arm64      | 88bafb10fa38 | yes    | Centos 8-Stream arm64 (20200714_07:08)   | aarch64      | CONTAINER       | 147.17MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/cloud/ppc64el    | 15eaf9ce55a4 | yes    | Centos 8-Stream ppc64el (20200714_07:08) | ppc64le      | CONTAINER       | 155.66MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8-Stream/ppc64el (1 more) | 6cedfe83c6b9 | yes    | Centos 8-Stream ppc64el (20200714_07:08) | ppc64le      | CONTAINER       | 140.54MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/arm64 (1 more)          | afb6965dbdfb | yes    | Centos 8 arm64 (20200714_07:08)          | aarch64      | CONTAINER       | 121.66MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/cloud (1 more)          | 6099bb04dc55 | yes    | Centos 8 amd64 (20200714_07:08)          | x86_64       | CONTAINER       | 140.05MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/cloud (1 more)          | f6d70e969faf | yes    | Centos 8 amd64 (20200714_07:08)          | x86_64       | VIRTUAL-MACHINE | 496.13MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/cloud/arm64             | b54ec18a6fdc | yes    | Centos 8 arm64 (20200714_07:08)          | aarch64      | CONTAINER       | 136.18MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/cloud/ppc64el           | 1011e9c98bda | yes    | Centos 8 ppc64el (20200714_07:08)        | ppc64le      | CONTAINER       | 144.22MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+
| centos/8/ppc64el (1 more)        | 2df6d6ca3e80 | yes    | Centos 8 ppc64el (20200714_07:08)        | ppc64le      | CONTAINER       | 129.11MB | Jul 14, 2020 at 12:00am (UTC) |
+----------------------------------+--------------+--------+------------------------------------------+--------------+-----------------+----------+-------------------------------+

おおいね。CPUアーキテクチャとかクラウド向けとかいろいろあって大変です。

2021-06-17

いくつかの要素が混じりすぎてて、後で読みにくかったので、CentOSに関するところを別の記事に仕立て直した。

https://takuya-1st.hatenablog.jp/entry/2021/06/17/164311

LXC とホスト間でディレクトリを共有する

LXC とホスト間でディレクトリを共有する

lxc で debian を作って、そこでnginx を運用していると、dockerで volumeの共有みたいにホスト・コンテナ間でディレクトリを共有したい。

docker だと EXPOSE で ディレクトリを、起動時にvolume を指定するだけでいけるけど、lxc はそこまでかんたんじゃない。

LXCでディレクトリの共有の場合

LXCでコンテナを起動していると、ユーザー名とuid がlinux の機能で擬似的にリマップされているので、同じディレクトリでもパーミッションをみるための ower / group のパーミッションがぐちゃぐちゃになるので、事前に設定しなくてはいけない。

/var/www/html をLXCで共有するとき

ubuntu の www-data(uid 33 / gid 33 ) のユーザーでホストとコンテナでディレクトリの共有をする。

/var/www/htmlをホストとコンテナで共有する事を考えてみる。

lxc ホストが ubuntu で lxc のコンテナも ubuntu で 両方をdebian 系で統一して試した。 /var/www/ は www-data ユーザで扱うので www-data ユーザをマッピングする設定がいる。

uid のマッピング

最初に、uid をマッピングの準備をする

takuya@lxc-host:~$ id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
takuya@lxc-host:~$ lxc exec ubuntu1804 id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)

www-dataがいないときは nginx / apacheがインストールされていないと思われる。

ホスト側で、www-data がオーナーのフォルダを作る

mkdir /opt/shared-www
chown www-data: -R /opt/shared-www

まず、ホスト側からコンテナ(ゲスト)に見せるフォルダを作る

ホストとコンテナの間でIDをマッピングする。

lxc config set ubuntu1804 raw.idmap 'both 33 33'

ホストとコンテナの間で、ディレクトリを共有するデバイスを作る

コンテナにディレクトリを渡すときは、設定は「デバイス」あつかいになるので config device 関連にまとめらている。

lxc config device add ubuntu1804 config-www-dir disk source=/opt/shared-www/ path=/var/www/shared

lxc config device で設定を確認する。

takuya@lxc-host:~$ lxc config device show vps
config-www-dir:
  path: /var/www/shared/
  source: /opt/shared-www/
  type: disk

再起動

最後に、IDマッピングを有効化し、 device disk を有効化するために、再起動する

lxc restart nginx

これでホストとゲストのコンテナの間でフォルダを共有することができる。

docker の expose のボリュームに比べて少し面倒ですね。

ポイント

ホスト・コンテナ間で uid/gidマッピングが必要

device config でデバイスとして追加する。

php で url から ホスト名を取り出す。 - parse_url

PHPでURLからホスト名だけを取り出す。

<?php  parse_url( $url, PHP_URL_HOST );

parse_url にフラグを入れるだけで、ホスト名を取り出すことができる。

実行するとこんな感じになります。

php > var_dump(parse_url( 'https://www.yahoo.co.jp:443/', PHP_URL_HOST ));

string(15) "www.yahoo.co.jp"

見て分かる通り、指定したものをちゃんと簡単に取り出せます。

ほんとなんで十分に検証もしないままコピペの正規表現パターンを書いちゃうんでしょうかねぇ。

parse_url 関数が多機能すぎるんでしょうか。

参考資料

https://www.php.net/manual/en/function.parse-url.php

php で DNS からレコードを調べてIPアドレスを取り出す - dns_get_record

ドメイン名のDNSレコードを調べてIPアドレスを取得する

dns_get_recordDNSの値をクエリすることが出来ます。

<?php
dns_get_record('www.yahoo.co.jp', DNS_A)

gethostbynameの、古くからあるIPアドレスを調べる方法を取ることが出来ます。

<?php 
gethostbyname('www.yahoo.co.jp'))

dns_get_record を使った場合の取り出し例

CNAME で指定されたDNSレコードの場合は、 DNS_A をフラグとして入れてあげると、IPアドレスが取り出せる。

php > var_dump(dns_get_record('www.yahoo.co.jp', DNS_A));
array(1) {
  [0]=>
  array(5) {
    ["host"]=>
    string(16) "edge12.g.yimg.jp"
    ["class"]=>
    string(2) "IN"
    ["ttl"]=>
    int(120)
    ["type"]=>
    string(1) "A"
    ["ip"]=>
    string(14) "183.79.219.252"
  }
}
php > var_dump(dns_get_record('www.yahoo.co.jp'));
array(1) {
  [0]=>
  array(5) {
    ["host"]=>
    string(15) "www.yahoo.co.jp"
    ["class"]=>
    string(2) "IN"
    ["ttl"]=>
    int(815)
    ["type"]=>
    string(5) "CNAME"
    ["target"]=>
    string(16) "edge12.g.yimg.jp"
  }
}
php >

参考資料

https://www.php.net/manual/en/function.dns-get-record.php

phpで文字列がメールアドレスかどうか調べる(RFC822) - filter_vars

phpで文字列がメールアドレスかどうか調べる。

<?php

filter_var('takuya@example.com', FILTER_VALIDATE_EMAIL ))

たったこれだけでRFC準拠のE-MAILのメールアドレスかどうかを調べることができる。

その他の出力結果はつぎのようになります。

php > var_dump(filter_var('takuya@example.com', FILTER_VALIDATE_EMAIL ));
string(18) "takuya@example.com"

php > var_dump(filter_var('takuya+sample@example.com', FILTER_VALIDATE_EMAIL ));
string(25) "takuya+sample@example.com"

php > var_dump(filter_var('takuya+sample@.com', FILTER_VALIDATE_EMAIL ));
bool(false)

php > var_dump(filter_var('takuya+sample@doc.com', FILTER_VALIDATE_EMAIL ));
string(21) "takuya+sample@doc.com"

php > var_dump(filter_var('takuya.@doc.com', FILTER_VALIDATE_EMAIL ));
bool(false)

php > var_dump(filter_var('takuya_1st@doc.com', FILTER_VALIDATE_EMAIL ));
string(18) "takuya_1st@doc.com"

php > var_dump(filter_var('tak.uya_1st@doc.com', FILTER_VALIDATE_EMAIL ));
string(19) "tak.uya_1st@doc.com"

php > var_dump(filter_var('tak..uya_1st@doc.com', FILTER_VALIDATE_EMAIL ));
bool(false)

RFC非準拠メールアドレスを捨てても大丈夫。

 むかしむかし、NTTドコモというメールアドレス発行者がいて、RFC非準拠メールアドレスを発行許可してくれました。 dd.@docomo.ne.jp のように@マークの前に ドットが入るものです。しかし現在では、ドコモのメールアドレスでは、@マーク前のドットは許可されされていません。スパムメール対策に敢えて準拠違反のメールアドレスを使うという暴挙が過去に行われていましたが、いまは昔です。

 Gmailでは ta..ku..ya@gmail.com のような ドットが連続するメールアドレスを使えましたが、これもいまは昔です。もう動きません。

 したがって、Phperが「妙ちくりん」なregular expression を書いたりコピペするよりも、FILTER_VALIDATE_EMAIL を使ってメールアドレスをバリデーションしたほうが確実なのです。

 なぜしないんでしょうね。コピペが横行していて、公式マニュアルを読まないのは少し不思議(SF)です。

メールアドレスのバリデーションは公式をまず使おう

php 組み込み関数 filter_var を使うほうが無難です。それでもどうしても対応できないものが出てきた時に、はじめてコピペや検索結果に出てくるアドバイスを見たらどうでしょうか。

<?php

filter_var('takuya@example.com', FILTER_VALIDATE_EMAIL ))

filter_vars に関するバリデーション一覧

https://www.php.net/manual/en/filter.filters.validate.php

マニュアルを少し見れば、変な正規表現パターンもテストも不要になるのではないでしょうか。

phpで 文字列がIPアドレスかどうか調べる- filter_vars

文字列がIPアドレスかどうか調べるには。

FILTER_VALIDATE_IP を filter_vars と組み合わせて使うとお手軽です。

<?php
function is_ipv4 ( $ip ){
  return filter_var($ip,  FILTER_VALIDATE_IP);
}

これで、v4かどうか調べることができる。

使い方と出力サンプルは次の通り

いくつかのタイプで調べてみると、動作がわかる。

php > var_dump(filter_var('a', FILTER_VALIDATE_IP));
bool(false)
php > var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP));
string(9) "127.0.0.1"
php > var_dump(filter_var('127.', FILTER_VALIDATE_IP));
bool(false)
php > var_dump(filter_var('1.1.1.1', FILTER_VALIDATE_IP));
string(7) "1.1.1.1"
php > var_dump(filter_var('192.168.1.1/24', FILTER_VALIDATE_IP));
bool(false)
php > var_dump(filter_var('192.168.1.1', FILTER_VALIDATE_IP));
string(11) "192.168.1.1"
php >

FILTER_VALIDATE_IP と filter_var の組み合わせでバリデーションが出来て、ちゃんと動作しているのがわかるでしょうか。

v6 かどうか調べるには

FILTER_FLAG_IPV6  を使います。ただし、組み合わせて使います。

<?php
php > var_dump(filter_var('2001:a240:8383:a300::1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ));
string(22) "2001:a240:8383:a300::1"

マニュアル読もうぜ。

なぜphper は自作のヴァリでーションを書いてしまうのか。正規表現パターンをいいけど言語組み込みの機能は積極的に使ってほしいと思うんですよね。

https://www.php.net/manual/en/ref.filter.php

ubuntu で apt インストールした mariadb(mysql) のroot パスワードがわからないので初期設定を探した

ubuntu 20.04 で mariadb-server

mariadb-server をいれたけど、デフォルトのユーザーパスワードがわからない!

mysql をインストールしたときは、ユーザーパスワードの生成プロンプトが出てきたのに、最近のapt はプロンプト出さない傾向があるんですよ、とくにserver版のやつ

インストール済みのmariadb に接続する

uid 1 で、 mysql ユーザーもroot でログインすれば、パスワードがいらない。

sudo mysql -u root 

試してみた

### ubuntu 一般ユーザー→だめ
ubuntu@primary:/var/www$ mysql
ERROR 1698 (28000): Access denied for user 'ubuntu'@'localhost'

### ubuntu 一般ユーザーが mysql ユーザー root として → だめ
ubuntu@primary:/var/www$ mysql -u root
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
### 上記の -p でパスワードプロンプト、、、パスワードが分からない。
ubuntu@primary:/var/www$ mysql -u root -p
Enter password:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
### sudo でやってみても、パスワードがないので詰まる。 未入力の状態でEnter → つながる!
ubuntu@primary:/var/www$ sudo mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 44
Server version: 10.1.44-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

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

MariaDB [(none)]>

デフォルトはsudo パスワード=なしでログイン可能ですね

というわけで、 デフォルトはパスワード=なしでログイン可能ですよね。これってある意味やばいので注意が必要です。ただし、sudo 出来ない限りは大丈夫。 sudo ユーザーを増やしている場合は注意が必要ですね。

インストールが終わったら

初期化とユーザー登録と権限設定ですね。

MySQLの基本的コマンド(ユーザ・DB・権限・パスワード)の設定削除作成の早見表 -- sql 版 - それマグで!

ランダムなひらがな文字列を生成する-ruby でひみつの質問

ひみつの質問の回答をジェネレーターで作る

(1..10).each do
  puts (1..20).map{|e| (0x3042+Random.new.rand(0..82)).chr(Encoding::UTF_8)}.join
end

実行サンプル

ランダムな文字列を生成するのである。

/usr/bin/ruby himitu.rb
ふぉゔゃまゅめゅいごなこきむてぎなざさへ
ぽぽはとごだんむごよぇねとほうそわをゎつ
ねぽねなやしいづびぽぉばぐひごろへでおよ
がづつぷほぼゑたやかゆぺえへまよもいおぇ
りねっせぶぢけぺねあとほごせよんうゐだひ
ろざゆぃくばへごつちきゎそぱたついさげへ
ずじへめやむぺゐふぃまえしづめゃおゅなし
ふもぺょけにゃぜつかぢきいぎけのすむぉで
りこぐぶやをのうぐぱにずぬえぞはめぶゑち
もとをぷゅぱひよぱぢずゃぽんさけまぼしけ

仕組み

UTF-8 で 0x3042 が’あ’

0x3042 + ランダムな数字

数字.chr( Encoding::UTF_8 ) で、文字コードの数字を、文字に変換

あとはこれを必要文字数文繰り返す。

バリデーションで弾かれる可能性がある。

'ゔ', 'ゕ', 'ゖ' の3つの文字は、バリデーションで「かな」ではないと弾かれる可能性が高い。

世間に出回る、ひらがなチェック正規表現"regex": /^[ぁ-んー\s]+$/ になっているので 、’んー’以降に存在する 'ゔ', 'ゕ', 'ゖ'はひらがなとして認識されないかもしれない。

関連資料

秘密の質問ジェネレータを、pythonでぱぱっと - それマグで!

ssh の秘密鍵は何ビットやFingerprintのプロパティ情報を見る

SSH秘密鍵が何ビットだったか忘れた

随分前に作った秘密鍵なので、これが1024 / 2048 なのかすっかり忘れていました。

ssh-keygen で秘密鍵の情報を確認

秘密鍵の情報をみるには、ssh-keygenコマンドでやります。

ssh-keygen -l -f ~/.ssh/id_rsa

このコマンドを使えば、ビット数やRSAキーかどうか、Finterprintなどが表示できます。

実行例

takuya@~$ssh-keygen -l -f ~/.ssh/id_rsa
2048 SHA256:ikqYC8kkcxFABO/1+uEDhlZqm9Czt takuya@host (RSA)

これで、秘密鍵の指紋(Finterprint)が確認でき、キーの名前や、バイト数(上記の例では2048) を調べることが出来ます。

参考資料

How To: Inspect SSH Key Fingerprints

Apache2でmod_rewrite が動かない?

Apache2 で rewrite エンジンを動か無いときにチェックするもの

久しぶりに、ubuntu にApache2+php いれて /aaa/aaa を /index.php/aaa/aaa に転送しようとしたら出来ない。

apache2 の場合、rewrite を使うまでにいくつか手順が必要

  1. rewrite が有効になっていますか
  2. Allow Override が使えるか
  3. htaccess の記述内容は正しいですか

rewrite を有効にして、有効になっているか。

apache の場合、rewrite を使ってリクエストのPATHをキャッチオールするので、有効にする

sudo a2enmod rewrite 
sudo apache2 configtest
sudo apache2 restart

Allow Override

apache2.conf で Allow Orverride を有効にする

Allow Orverride はディレクトリに対する設定で書くので、apache2.conf に書く。

 <Directory /var/www/>
   Options Indexes FollowSymLinks
   AllowOverride All
   Require all granted
 </Directory>

.htaccess の記述

.htaccess の記述を確認する。rewrite を有効にしているかチェック

<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !^(.*)\.(gif|png|jpe?g|css|ico|js|svg|map)$ [NC]
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

rewrite を使う時

rewrite は標準でインストールされるが、htaccess で使うのに Allow Override がhttpd.confに必要で、一回書くとずっと使うので忘れますね。

nginx だと rewrite のルールは nginx のconfig に書くので、更に忘れますね。

参考資料

Apache/Apacheでmod-rewriteが動かない場合の原因のいくつか - Web関連技術調査

シェル ( /bin/sh ) での正規表現マッチ。

以前、bash正規表現について書いた。

今回は、今更だけど、あえて、bash/zsh で使われている [[ を使わずに、正規表現を使おうとしてみた。

expr よりは bash の機能を使ったほうがいい。

以前書いた記事にある。bash/zsh正規表現を使う方法が個人的には優れていると思う。

takuya-1st.hatenablog.jp

どうしても sh じゃないとだめなんだったときは expr を使う選択肢になる。

/bin/sh の場合は expr で正規表現を扱う。

シェルの正規表現は、次のようにかける。

expr "なにか文字列" : "regex"

または、次のように書く。

expr match "なにか文字列"  "regex"

expr は expression の略だったかとおもう。Expressionの名前の通り、文字列表現の式を評価をする。四則演算なども使います。

expr を使う上での注意。

expr は式を評価するので、結果がプリントされます。

通常の [ / test は結果をプリントせずにステータース・コードをexit code で返しますが、expr は文字列を出力するので注意。

expr で正規表現

正規表現をするときは次のように書きます。

expr hello :  'h.*o' 

または

expr match hello   'h.*o' 

if 文 と expr でマッチングで条件分岐

expr を正規表現マッチで返すと一致したかどうかを文字列でプリントするので、出力を捨てる必要がある。

if expr hello :  'hello' > /dev/null ; then
  echo match
fi

サンプル

正規表現/bin/sh で動くように regex をexpr で扱ってbashだけでなく汎ゆる場所で動くことを想定したらこんな感じになるが

#!/bin/sh


match_test () {
  printf "%-18s:" "$1"
  if expr "$1" : '.*apple' > /dev/null ; then
   echo match
  else
    echo does not match
  fi

}

match_test "Hello World."
match_test "This is an apple."
match_test "This is a pen."

実行結果

上記の実行結果

$ ./test.sh
Hello World.      :does not match
This is an apple. :match
This is a pen.    :does not match

細かい部分で [[ と違う。

正規表現の柔軟度を考えると、bash / zsh に組み込まれている [[ を使ったほうが正規表現の書きやすさ、マッチ判断のわかりやすさが上回っている。

関連資料

bashでif に正規表現を使った文字列マッチ条件分岐 - それマグで!

Vimのet / noet って何?→expandtab です。

vimrc の設定ファイルでet を見かける

et ってなんだよ!ってことを感じたのでメモ。

set et  " set expandtab と同等
set noet  " = set noexpandtab 

noetno + et ですね。

vimrcなどvim の設定ファイル は noXXX で表記されることが多いですね。set nonumber 略して set nonuなど。

expandtabetなので、noexpandtabnoet ですね

expandtab ってなに

タブ文字入力をスペースとして扱うやつです。どのサイズになるのかは ts=2 ( tabstop=2 ) などで調整します。

expandtab(et / noet ) を設定するときは併せて ts / sw を調整しましょう

参考資料

:set expandtab(:set et)設定の時に、タブ文字を挿入する — 名無しのvim使い

Vim のカスタマイズ 〜 タブ/インデントの設定 〜 - Vim のブログ

ruby でGmail(smtp) 経由でメールを送信する。TLS有効化

ruby でメールを送信する

ruby からgmail を送信するには、 mail ライブラリだけでも出来るんだけど。

MIMEエンコードされたデータを受け取ってそのまま forward するには、もう少しいい方法がないかなと思って考えていた。

メールリレーの中間に入って、指定メールだけを転送したいとか、smtp-proxy を作っておきたいとかそういうときに活用できる。いちいちデコードして作り直しててめんどくさくてですね。

net/smtpgmail 送信。

require 'bundler'
Bundler.setup
require 'net/smtp'
require 'mail'
require_relative '../etc/gmail-passwd'



smtp = Net::SMTP.new("smtp.gmail.com", '587')
smtp.enable_starttls
smtp.start(
    'smtp.gmail.com',
    $gmail_account.username,
    $gmail_account.password,
    :login
)

mail = Mail.new
mail.from = "webmaster@example.com"
mail.to  = "takuya@example.com"
mail.subject = "test"
mail.body ="test test"
mail.attachments["photo.jpg"] = File.binread( File.expand_path( "./photo.jpg",  File.dirname($0) ) )


smtp.send_mail( mail.encoded , mail.from, mail.to )

これで、ファイルを入れているプロジェクトで bundle install したら大丈夫。

添付ファイルの準備。

送信テストで添付ファイルを使いたいので準備します。

convert -background white -fill black -pointsize 256 label:'Hello World' photo.jpg

送信テスト。

bundler init 
bundler add mail
bundler install 
ruby test-mail.rb

これで送信できます。

Mailのみの場合

mail ライブラリで新規メール作成して、送信するにはMail だけでいける。

require 'mail'


mail = Mail.new

mail.delivery_method(:smtp,
                     address:        "smtp.gmail.com",
                     port:           587,
                     domain:         "smtp.gmail.com",
                     authentication: :login,
                     user_name:      $gmail_account.username,
                     password:       $gmail_account.password
)


mail.from = "webmaster@example.com"
mail.to  = "takuya@example.com"
mail.subject = "test"
mail.body ="test test"

mail.deliver

redis のクライアントだけをインストールする。

redis に接続するクライアントだけインストールしたい

redis のクライアント redis-cli は次のコマンドでインストールする。

sudo apt install redis-tools

これで redisに接続して、データのやり取りをモニタリング出来る。