それマグで!

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

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

Goole App Script ( GAS ) の基本的な操作方法。08.デバッガとグローバル・オブジェクト

前回まで

前回までで、スクリプトを作って、ファイルに分割してクラスに分けて管理するまで見た。

そろそろまともなコーディングができそうな気がする

今回は

今回はデバッグを使う。デバッグツールを使いGlobalオブジェクトを確認する。

デバッグで実行

行番号をクリックしてブレークポイントを設置できる。

f:id:takuya_1st:20210604033900p:plain

ブレークポイントで止めておけば、グローバルオブジェクトをすべて参照できるので便利。

グローバルオブジェクトの一覧

デバッガを起動しブレークポイントで止めてけば、グローバルオブジェクトの一覧を見ることができる。

global な object 一覧は一度見ておくと、スッキリする。

意外なオブジェクトがあったりする。あと名前のルールが分かっていいと思う。

f:id:takuya_1st:20210604034006p:plain

Utilities クラスとかあったりする。

続く

長いので分割しました。

次回に続く→09

Goole App Script ( GAS ) の基本的な操作方法。07.クラス作成でコード管理。

前回の続き

前回までで、スクリプトを実行し、関数に分割して管理、ファイルに分割して管理、ネットアクセスまでみた。

今回はクラス

今回は、ファイルに分割してするだけじゃなく、クラスにまとめるほう法をみて、さらにコードをスッキリさせる方法を見ておく。

classを使う。

class も完全な互換性があるわけでないが、ある程度使える。

ちょっと古い書式のJavaScriptのclassなので、たまにイライラするかもしれない。

クラスのサンプル

次のようなクラスをGASに作って実行してみます。

class MyClass{

  constructor() {
    this.name = "taro";
  }
  say(){
    console.log( ` My Name is ${this.name} ` )
  }
}
class Dog extends MyClass{

}

function main(){

  let obj = new Dog();
  obj.say()

}

クラスを使った実行

クラスを使ってコードを書いたら、そのあとの関数で実行ができる。

f:id:takuya_1st:20210604033553p:plain

実行結果は次のようになる。

f:id:takuya_1st:20210604033543p:plain

続く

長いので分割しました。

次回に続く→08

             

         

 

Goole App Script ( GAS ) の基本的な操作方法。06. HTTPアクセスでJSON取得

前回の続き

前回までで、ハローワールドを書いて、ファイル分割して管理できるまでみた。

今回は、ネットアクセス

今回は、URLへリクエストを投げて、Google外部のAPIを使ってデータ連携する方法を見ておく。

ネットからデータを取得

URLを指定して、HTTPアクセスでデータを取得したり、データを送信できる。外部のAPIと連携して通知を送ったりできる。

URLへHTTP GET

HTTPでGET もできる。UrlFetchAppオブジェクトがグローバル空間に存在する。UrlFetchAppを使えばオッケ

function  getCurrentIp(){
  let url =  'https://api.ipify.org?format=json'
  let json = UrlFetchApp.fetch(url);
  let obj = JSON.parse(json);
  console.log(obj)
}

HTTPアクセスの結果例

f:id:takuya_1st:20210604052453p:plain

ちなみに、IPアドレスを取得すればわかるんですが、スクリプトは自分のPCで動いてるんすね。 てっきりリモートで動いていると思ってました。

URLにPOSTしてデータを取得 / HTTP POST

fetch の第2引数を指定すれば、POSTを使える。method にPOSTを入れるのですが、POST・GET以外は使えないようですね。

function  getCurrentIp(){
  let url =  'https://api.ipify.org'
  let options = {
  'method' : 'post',
  headers: { "Content-Type": 'application/json' },
  'payload' : 'format=json'
  };
  let json = UrlFetchApp.fetch(url,options);
  let obj = JSON.parse(json);
  console.log(obj)
}

続く

長いので分割しました。

次回に続く→07

Goole App Script ( GAS ) の基本的な操作方法。05. 複数ファイルに分割

前回まで

前回までで、スクリプトを使ってスプレッドシート側に操作ができるようになった。

今回は、ファイル分割。

単純な作業であれば、1つのファイルに全部書いていけばいいのでしょう。 しかし、まともにスクリプトを書くなら、ファイルに分割して書きたくなります。

今回は、ファイル分割をしてスクリプトを使う方法を見ていきます。

関数ファイルを追加する。

最初に用意されるファイルはコード.gs ( 英語版は CODE.gs )がファイル名のデフォルトになっている。

好きなファイル名で追加することができる。

メニューからファイルを追加を選んで押す。

f:id:takuya_1st:20210604032805p:plain

スクリプトを選ぶ

f:id:takuya_1st:20210604032813p:plain

好きな名前でファイルを追加できる。拡張子は入力不要

f:id:takuya_1st:20210604032819p:plain

関数はグローバル空間に追加される。

作成したファイルは、起動前にすべてロードされる。そしてファイル中のグローバルな空間に関数として追加される。関数を追加するといつでも使えると思っていい。

関数以外のスクリプト

関数じゃなく、次のようにベタ書きしたスクリプトは、スクリプト起動前に実行される。

f:id:takuya_1st:20210604033016p:plain

これは、関数を実行する前に実行されます。タイミングはロード時です。関数実行前に、全ファイルをロードします。関数外のスクリプトは、このロード時に実行されるので注意。

ロード順=ファイル名の順

ロードの順序はファイルの順序(名前順)になる。ロード時に実行される関数を作るのであれば、ロード順にも配慮しないとだめ。

たとえば、同名の関数があれば後から読まれた関数で上書きされる。

ファイル名の順番でロードが後になるファイルで先のファイルに書かれた関数が、上書きされる。そのため後ファイルに置いた関数が優先される。

デフォルトの myFunction は、名前被りが多いです。ロード順に注意しないと、関数が実行されない。と悩む原因になります。

続く

長いので分割しました、次回に続く→06

      

takuya-1st.hatenablog.jp

        

  

   

Goole App Script ( GAS ) の基本的な操作方法。04.セルにハローワールド

前回の続き

前回までで、ハローワールド、関数を指定した実行、スプレッドシート側にハローワールドまでやった。

今回はドキュメント側に書き込む。

スプレッドシートにハローワールドを書き込んでみる。

スプレッドシートにハローワールドを書き込む。

スプレッド・シートのセルにハローワールドを書き込む。

function HelloworldToCell() {

  let app = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = app.getActiveSheet();
  let range = sheet.getRange('A1');

  range.setValue("Hello World.");
}

書き込んだら、実行します。

f:id:takuya_1st:20210604032325p:plain

権限が付与されたら、セルにハローワールドが入力される。

f:id:takuya_1st:20210604032313p:plain

続く

長いので分割しました。次に続く→05

           

Goole App Script ( GAS ) の基本的な操作方法。03.ダイアログでハローワールド

前回の続き

前回までで、コンソールにログをとして出力する。

今回は、スプレッドシートと連携する。

スプレッドシートと連携してハローワールドをスプレッドシート側に出す。

スプレッド・シートに出力ーダイアログ

スプレッド・シートにハローワールドをダイアログとして表示する。

スクリプトエディタで、Browser.msgBox関数を書き込んでいく。
このとき、補完を体験しておく。

Broと打てば補完が効く。

f:id:takuya_1st:20210604031659p:plain

続けて msgBox で補完が効く。

f:id:takuya_1st:20210604031716p:plain

ダイアログを表示する関数を作った

f:id:takuya_1st:20210604031623p:plain

実行する

f:id:takuya_1st:20210604051146p:plain

実行ボタンを押して権限を承認。

実行すると、権限チェックを求められます。

スクリプトGoogle Spreadsheetにアクセスする権限が必要になります。

権限はそのまま許可してあげればオッケです

f:id:takuya_1st:20210604031413p:plain

ダイアログが表示される。

権限の画面遷移が終われば、ダイアログが表示される。

権限は、初回起動時のみで、次回以降は権限があるので確認されない。f:id:takuya_1st:20210604031415p:plain

実行者ごとに権限。

自分のアクセスに関するアクセス権限なので、別人物(別アカウント)が実行するときにはまた別に権限が必要になる。

スクリプトはローカル

スクリプトはあくまでJSなので、ローカルのブラウザ内部で実行され。そのために、リモートにあるGoogle Spreadsheetへアクセス権を要求する。などと考えたら理解しやすいと思う。

続く

長いので分割しました。次に続く→ 04

     

   

Goole App Script ( GAS ) の基本的な操作方法。02.関数の追加

前回の続き

前回はハローワールドを実行した。

今回は関数を追加する。

関数を追加して、実行する。

関数を追加する。

2つ目の関数を作って使う。関数を作って使うために、サクッと関数を作る。

f:id:takuya_1st:20210604031135p:plain

実行する関数を選ぶ

関数は実行時に選択する必要があるので、作った関数を選択する。

f:id:takuya_1st:20210604031240p:plain

関数を選んでから実行する

関数を選んでから実行ボタンを押す。

f:id:takuya_1st:20210604031247p:plain

実行ログ。

結果が出てくる。

f:id:takuya_1st:20210604031322p:plain

console.log は実行ログ。

console.log は、実行ログとしてスクリプト・エディタに表示される。スクリプト・エディタでの実行ログは初期ロード時に非表示なので、画面構成が変化 するのですぐ気づけると思う。

続く

長いので分割しました。次回に続く→ 次 03

     

 

  

Goole App Script ( GAS ) の基本的な操作方法。01.コンソールでハローワールド

GAS を始める。

GAS を始めるときに、最初に手順を覚える。

最初の流れ。

  1. Google Driveで新規スプレッドシートを作る
  2. スプレッドシートを開ける。
  3. ツールからスクリプト・エディタを開く
  4. ツールから実行する

この記事で取り扱うこと

  • スクリプトエディタの起動
  • ハローワールドの実行(コンソール)
  • 関数の追加と実行
  • スプレッドシートにハローワールド(ダイアログ)
  • スプレッドシートにハローワールド(セルに記入)
  • 複数ファイル分割
  • ファイルのロード順
  • 最初に実行される関数
  • メニューで実行
  • ボタンで実行
  • ショートカット

準備 / Google Driveで新規作成する

Google Driveで新規スプレッド・シートを作って、そのファイルを開く。

スプレッドシートを作り開く

右クリックメニューから新規、スプレッドシートを選んで、新規作成

f:id:takuya_1st:20210604025908p:plain

スクリプトエディタを開く

スプレッドシートが開いたら、メニューからスクリプトエディタを選択する

f:id:takuya_1st:20210604025922p:plain

スクリプト・エディタを別のウインドウにする

スクリプトエディタが別タブで開く。スクリプトエディタとスプレッドシートはペアで使う。

別ウインドウにしておいたほうが、動作チェックが楽。たくさん試すときは、別ウインドウにしておくほうがいい。

f:id:takuya_1st:20210604025932p:plain

別ウインドウで開いておけば、スクリプトを実行したときにすぐに結果がわかる。視覚的にわかるので便利。

f:id:takuya_1st:20210604025935p:plain

GAS でハローワールド

console.log でハローワールドを書く。

f:id:takuya_1st:20210604030401p:plain

実行ボタンを押す。

上部メニューから、実行を押す。

f:id:takuya_1st:20210604030403p:plain

下部に実行結果が出てくる

下部の実行ログの部分に、実行結果が表示される。

f:id:takuya_1st:20210604030550p:plain

続き

長いので、分割しました。

次に続く→02 

  

  

potainer でユーザとチーム毎に管理できるホスト(endpoint)を設定する。

ユーザ毎にアクセス権(利用可不可)設定する。

Portainer は「Role単位の詳細権限」については、Bussiness版が必要なのだが、

チーム(グループ)とユーザ毎に、このDockerホストを許可する許可しないと設定できる。

少しわかりにくかったのでメモ。

f:id:takuya_1st:20210531153354p:plain

Endpoints の右カラムから行う。

Portainerに登録された、エンドポイント(サーバー)を1単位として、ユーザにアクセス権を設定できる。 これで、複数のPotainerを起動しなくて済ませられるのは熱い。

f:id:takuya_1st:20210531153813p:plain

アクセス権とユーザー単位で分けておけば、不意に他の人のインスタンスやサーバーをダウンさせてしまうことが減るので便利ですね。

事前にエンドポイントを設定する必要がありますけど。エンドポイントはdocker in docker は docker in lxc などで増やしてしまえばいいので。

docker別ホストから接続、管理SockをTCP経由許可して利用する。

docker の管理を別ホストから行いたい

ほとんどの人はDockerが動いているマシンへ SSHで接続してるともう。

ssh 経由で docker を使う場合

作業用PC ----<SSH>---- docker-host

リモートのDockerがインストールされたマシン中でdocker コマンドを叩いている場合

接続の詳細。

実際には接続がUNIX のソケット経由になっている。

作業用PC ----<SSH>---- docker-host----<unix:/socket>----/var/run/docker.sock

ん?unix/socket?そうですね。ソケットファイル経由です。
「だったら、ファイルじゃなくポートをリッスンすれば直接つながるのでは?」と思った貴方は大正解です。

tcp 接続でダイレクトに接続できる。

docker は TCPリッスンできるので、socket を経由しなくてもダイレクトに接続ができる。

作業用PC --------------- tcp ----------------- docker-host

SSH経由に比べると、ポートは開きっぱなしだし、認証関係もすっ飛ばすし、危険性が高いように思えるかもしれないが 仮想マシン間、開発マシンと仮想マシン、ローカル内部でこれを使うとサクッと接続できるので、便利です。

Docker のTCP接続を有効にする

-H を使って tcp へのリッスンを追加する。

/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

ただしfd を消しちゃうと socket ファイル経由で接続ができなくなる。

ubuntu の docker にTCPをリッスンさせる

ubuntu で apt install docker.io でインストールした apt のdocker の場合、起動管理をsystemd が行っているのでsystemd のサービスファイルを書き換える。

sudo vim /lib/systemd/system/docker.service

該当サービスの ExecStartに -H tcp://0.0.0.0:2375 を追記する。

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

systemd をリロードして docker を再起動する

sudo systemctl daemon-reload
sudo systemctl restart docker

これでTCP経由で接続ができる。

クライアント側から docker接続する

docker コマンドは、DOCKER_HOST 変数で接続先を任意に指定することができる。

DOCKER_HOST=tcp://192.168.100.100:2375 docker ps

または、継続的に変数に入れてあげる。

export DOCKER_HOST=tcp://192.168.100.100:2375
docker ps 

これで、docker を任意のマシンからSSHすることなく操作ができる。

2375 はデフォルトのポートでWindowsのDockerが初期インストール時にデフォルトに設定されていたので。同じものにしました。

portainer / windows docker で使われています。

この機能、portainer や docker windowsで公式に使われています。注意深く見ていると気づいたと思います。

この公式機能であるポートリッスンを使えば、いちいちSSHしなくていんですよね。

portainer などと組み合わせる。

portainer など docker 管理のシステムと組み合わせるときにどうしてもこれらの設定が必要になってくる。

ポート管理に注意

ローカル中のdocker であれば、権限は ユーザーごとに決めることができるが、TCPをリッスンしてしまうと制御不能なので、取り扱い注意ですね。*1

参考資料

How do I expose the docker API over TCP? - Server Fault

*1:前時代のtcpwrapperやxinetd的な systemd.socketを間に挟んでゴニョゴニョすればできるんだろうけど

docker で systemdが動く ubuntu イメージを作って遊ぶ-その2

前回、systemd を動かした。

前回の続き

docker の起動コマンドを /sbin/init にすれば、 docker の ubuntu でも systemdを使って遊べることがわかった。

単純な作業だったので、dockerfile でイメージ化して遊ぶ

dockerfileを作って遊ぶ

FROM ubuntu:20.04
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends init

ENTRYPOINT ["/sbin/init"]

ビルド

dockerfileをビルドしてイメージにする。

docker image build -f Dockerfile -t ubuntu-systemd .

イメージを起動

コンテナは特権コンテナのほうが楽だけど、他に同じようなことをやってるひとを github見つけた。 その人の使ってるセキュリティ起動オプションを使う。

docker run -d   \
  --security-opt seccomp=unconfined \
  --tmpfs /tmp \
  --tmpfs /run \
  --tmpfs /run/lock \
  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
  -t ubuntu-systemd:latest

無事に起動することがわかる。

確認

nginx をインストールして systemd 経由でちゃんと起動するか確かめてみる。

docker exec -it 56e -- apt-get install nginx  --no-install-recommends
docker exec -it 56e systemctl status nginx
docker restart 56e systemctl status nginx
docker exec -it 56e systemctl status nginx

nginx が再起動後に起動することがわかる。

takuya@ubuntu:~/ubuntu-systemd$ docker exec -it 56e systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:nginx(8)
takuya@ubuntu:~/ubuntu-systemd$ docker exec -it 56e systemctl start nginx
takuya@ubuntu:~/ubuntu-systemd$ docker exec -it 56e systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2021-05-25 17:16:51 JST; 1s ago
       Docs: man:nginx(8)
    Process: 611 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 612 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 613 (nginx)
      Tasks: 5 (limit: 1388)
     CGroup: /system.slice/snap.docker.dockerd.service/system.slice/nginx.service
             ├─613 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             ├─614 nginx: worker process
             ├─615 nginx: worker process
             ├─616 nginx: worker process
             └─617 nginx: worker process

May 25 17:16:51 56e5331be46b systemd[1]: Starting A high performance web server and a reverse proxy server...
May 25 17:16:51 56e5331be46b systemd[1]: Started A high performance web server and a reverse proxy server.
takuya@ubuntu:~/ubuntu-systemd$

まとめ

/sbin/init もちょっとしたことで動くんだね。

でも公式でやってないということは・・・

遊べることがわかったけど、公式でやってないということは。何らかの問題があるのでサポートしてないんだろう。

また、先人がやってないということは、この手法を突き詰めることは徒労に終わる可能性が高いので、遊ぶのはここまで。

systemd は本当に多機能なので、直接使うと無駄が多いとか、そういう理由で supervisord を使ったりするかも。

docker の設計思想がシングルプロセスなのでdocker-composeを使うんですよ。きっと

例えば systemd-multiuser.target

マルチユースなマルチユーザーを前提にした multiuser や logind はいらないよね。

そう考えるとやっぱり無駄が多そう。

例えばシャットダウン

シャットダウンはできない。

root@db1ccf6f38c6:/# ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         678  1.0  0.0   4108  2540 pts/1    Ss   18:30   0:00 bash
root         686  0.0  0.0   5896  2140 pts/1    R+   18:30   0:00  \_ ps auxf
root           1  0.5  0.0  16308  5020 ?        Ss   18:27   0:01 /lib/systemd/systemd-shutdown reboot --timeout 90000000us --log-level 6 --log-target kmsg --log-color

シャットダウンできるわけでもない。

次のようなsystemctl が使いたいだけにはヘビィすぎる。

systemctl restart nginx 

systemd は本当に巨大なので、必要な部分だけ取り出して使おうとすると、ちょっとめんどくさいですよね。

追記 Windows Dockerで動かした場合

WSL2のWindowsなDockerで動かした場合、特権なしで動きました。

もしかして世間にあふれるブログ情報でsystemd / init を動かしたと書かれていたらWindowsでの話かもしれません。

WindowsのDocker (WSL2・Hyper-V)で動かした場合に特権なしで動いている例。 特権なしの代わりに sys_admin のCapabilityをADDしています。

参考資料

GitHub - bdellegrazie/docker-ubuntu-systemd: systemd-enabled versions of Docker base images

https://stackoverflow.com/questions/39169403/not-able-to-use-systemd-on-ubuntu-docker-container

dockerで systemd が動く ubuntu を作って遊ぶ - それマグで!

dockerで systemd が動く ubuntu を作って遊ぶ

はじめに

docker ではシングル・プロセスが前提なので、複数のプロセスを起動するべきではない。

それでも、ちょっと動かしてみたいと思うのが、遊びゴコロってやつ。docker で systemd を動かしてみたらどうなるのか。

今回は、Raspi4 の高速マシンがあるから遊んでみようと思います。

前提

docker がインストールされたホストOS。

完全仮想化か物理ホスト上で試す。

仮想化中のdockerなどは権限設定が大変なので考慮しない。 docker in docker だとか、 docker in lxd とかは動作がおかしくなる可能性があるんで、今回は考慮しない。

準備 raspi に docker インストール

素の ubuntu に、 docker をインストール。

最初に、ubuntu for raspberry pi 4 を持ってきて、raspiに ubuntuをしている。この素のubuntu に docker をインストール

snap 経由で docker をインストールする。

sudo snap install docker 

snap のdocker は一般ユーザからコマンドを使えないので、グループを追加して、パーミッションを変えて一般ユーザでもdocker コマンドを扱えるようにする。

自分自身のユーザをdocker グループに追加する。 groupadd と usermod でぱぱっと

sudo groupadd docker
sudo usermod -aG docker $USER

docker の socket ファイルの権限を chown で変えておく。

sudo chown root:docker /var/run/docker.sock
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R

docker サービスを再起動。

sudo reboot 
## または
systemctl restart docker.service

これで準備が完了。

ubnutu(systemd)な-docker を作る 全体の流れ

全体の流れはざっくりいうと、systemd をインストールしてイメージ化、その後に起動コマンドをsystemdの /sbin/init にして作成したイメージを起動する

  • ubuntu を起動する
  • systemd をインストール
  • イメージとして保存
  • イメージを起動(起動コマンドは /sbin/init)

イメージを作成するのがちょっとしたポイントだと思う。

systemd をdockerで使うポイント

docker で ubuntu を systemd で起動する。これをするにはいくつかのポイントがある。

  • docker ubuntu では systemd が含まれてない。
  • systemd を起動するには権限が必要
  • systemd は /sbin/init で起動する
  • docker は起動するプロセスを指定する
  • docker run で起動するプロセスは /sbin/init にする

これらのポイントをちょっとだけ見ておく。

systemd は /sbin/init の代替として /etc/init.d から upstart から 置き換えられたプロセスで PID=1としてすべてのプロセスの祖先になる。

docker は 敢えて /sbin/init を外すことでシステム起動をプロセス単位に分離している。その代わりに docker run で起動するコマンドをしていて起動する。

これらを考慮すると、何らかの形で /sbin/init をインストールしたイメージを作り、docker run で /sbin/init を指定すれば起動するのではないかと思われた。

systemd で起動する ubuntu イメージを作る。

最初にすることは systemd init がインストールされたUbuntu を作りイメージとして保存し、イメージとして取り込む。

#

最初に、ubuntu をdocker で起動して、/sbin/init をインストールしてやる。

docker run --rm  -it  ubuntu:latest

ubuntu は起動コマンドを指定しないと bash が起動する。

起動した ubuntu で、systemd をインストールする

apt update 
apt install init 

この状態で、ログインしたまま起動状態を維持ておく。

別のターミナルを立ち上げて、起動中のdocker インスタンスをイメージとして取り出す。

別ターミナルからイメージ作成

docker 起動中のコンテナIDを調べて、tar ball ファイルとして取り出す。

docker container export bcdfc201cd09 > ubuntu-init-installed.tar

イメージが作成できたら、initをインストールしたインスタンスは不要なのでbashをCtrl-Dで終了しインスタンスを消しておく。

イメージを取り込む。

イメージが作成できたら、作成したファイルをdocker image として取り込む tar のファイルを イメージとしてインポートする。

docker image import ubuntu-init-installed.tar  takuya/ubuntu-init-installed:latest

takuya/ubuntu-init-installed:latest は イメージの名前とTAG を指定してる。イメージ名がtakuya/ubuntu-init-installedで、タグがlatest である。

systemd を指定して、docker イメージを起動

インポートしたイメージを起動する。

docker は指定したプロセスを起動するのので、systemd 経由で起動するように、/sbin/init を指定して起動する。

ただし、/sbin/init はインタラクティブシェルを提供しないので、 デタッチで起動する。

また、ここで 特権コンテナ--privilegedを指定する 。特権をコンテナでないとsystemd は動いてくれない。

docker run --privileged --rm -d takuya/ubuntu-init-installed /sbin/init

起動の確認

特権をコンテナで無事に起動すると dbus などが使えるので通常通りのsystemdなubuntu とほぼ同じ状態で起動する。

ちゃんと/sbin/init がPID=1で起動しているのがわかる。

 docker exec -it 356f77ee1bb1 ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          51  0.0  0.0   5468  2452 pts/0    Rs+  03:29   0:00 ps auxf
root           1  3.6  0.1 165800  9244 ?        Ss   03:29   0:00 /sbin/init
root          21  1.4  0.1  34648 10488 ?        S<s  03:29   0:00 /lib/systemd/
systemd+      33  0.9  0.0  20964  6240 ?        Ss   03:29   0:00 /lib/systemd/
systemd+      34  0.9  0.0  89940  3704 ?        Ssl  03:29   0:00 /lib/systemd/
message+      37  0.1  0.0   7948  3596 ?        Ss   03:29   0:00 /usr/bin/dbus
root          39  1.6  0.2  26124 16820 ?        Ss   03:29   0:00 /usr/bin/pyth
root          41  0.6  0.0  16028  6124 ?        Ss   03:29   0:00 /lib/systemd/
root          45  0.0  0.0   2344  1484 ?        Ss   03:29   0:00 /sbin/agetty

あっさりと起動した。ずいぶんと拍子抜けである。 docker ではマルチなプロセスを管理するべきではないと言われて久しいが、動くものは動くのであるな。

nginx / ssh が有効になったイメージを作ってみる。

nginx や ssh が有効になったイメージを作ってみる。

systemd がインストールされた ubuntu を作れたので nginx / ssh をインストールして 起動と同時に ssh と nginx が起動するイメージの作成を試みる。

systemdなubuntuを起動して

docker run --rm --privileged -d takuya/ubuntu-init-installed  /sbin/init
docker exec -it 8f72eab2c5be  apt install openssh-server nginx

イメージとして取り出してインポート

docker export 8f72eab2c5be > ubuntu-init-installed-with-ssh-nginx.tar
docker image import ubuntu-init-installed-with-ssh-nginx.tar  takuya/ubuntu-init-installed:ssh
docker run --rm --privileged  -d takuya/ubuntu-init-installed:ssh  /sbin/init

チェックすると。問題なく動きますね。

 docker exec a2ef6147fdc systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2021-05-25 03:54:03 JST; 22s ago
       Docs: man:nginx(8)
    Process: 40 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 48 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 52 (nginx)
      Tasks: 5 (limit: 9257)
     CGroup: /docker/a2ef6147fdcc209a31cd1774234b461c20a85c9540e29b910089e5a44935fe20/system.slice/nginx.service
             ├─52 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             ├─53 nginx: worker process
             ├─54 nginx: worker process
             ├─55 nginx: worker process
             └─56 nginx: worker process

May 25 03:54:03 a2ef6147fdcc systemd[1]: Starting A high performance web server and a reverse proxy server...
May 25 03:54:03 a2ef6147fdcc systemd[1]: Started A high performance web server and a reverse proxy server.

あっさり動いてしまうんですね。

特権コンテナに注意。

特権コンテナは docker in docker のような特殊な用途であったりする目的のためにある。

あれこれ細かいところは省きますが、特権コンテナを使うので公開サーバーに利用は控えること。

用途

docker で apt を試したいときや、仮想マシンを起動するほどもでもない開発環境で export してぱぱっと渡したいとき。 初心者が多い開発チームなど、トラブルを回避するために一時的に export して import させてぱぱっと開発環境を再現させたり。とか便利そう。

ちょっと開発環境でインストールを試したいときとかそういうときにも便利そうですね。

dockerfile

動作の仕組みさえわかれば、dockerfile で systemd を書くことも不可能ではなさそう。私は開発環境でちょっと試したいとかなのでdocker export で満足しているので試さなかった。

まとめ

/sbin/init をインストールした状態で privileged で起動すると動かせる。

raspi4 8GB はマジ高性能なので実験環境に最適だった。

ただし、arm(aarch64)なraspiからx86_64 なamdは相互にexport/import出来ないはずなのでそのへんはちょっと注意。

特権コンテナには十分に注意しないといけない。特権コンテナは通常の物理ホストと何ら変わりなくdocker の仕組み上プロセスやファイルが分離されているようなことはない わかりやすいトラブルとして、 このコンテナが乗っ取られたときに、 docker 内部 docker をインストールされてしまい、docker run -v /:/real-hostと内部でマウントされてしまうと目が当てられない。

参考資料

macOSのFinderからクイックアクション(回転・マークアップ)のパネル(ペイン)を永久追放で削除する。

macOS Mojave から搭載された画像のクイックアクション

クイックアクション、正直言って邪魔ですね。Finderのプレビューペインが、スクロール化してしまい「プレビュ」が隠れるというトンデモ仕様。

プレビューを機能を覆い隠すとかちょっと信じられないんですよね。クイックアクションより、プレビューのほうが利用頻度が高いのに。プレビューがスクロールして隠れてしまう上に、ひどいときには横スクロールまで表示されしまう。耐えられない。消す方法を調べた

表示からプレビューオプションを選択。

手順としては、次の通り。

  1. クイックアクションが表示された状態で
  2. Finderの表示メニューを開く
  3. プレビューオプションを開く
  4. クイックアクションをオフにする。
  5. これをすべての拡張子で繰り返す。

この手順で、クイックアクションを削除することができて、プレビューペインで情報をスクロールすることなく確認することができる。 スクロールがおかしくなる違和感も解消される。

実際の設定

f:id:takuya_1st:20210523123840p:plain:w300

f:id:takuya_1st:20210523123218p:plain

f:id:takuya_1st:20210523123201p:plain:w300

すべての拡張子で繰り返す

ここが、まじ「頭おかしい」とおもってmacOSを窓から投げ捨てたくなり、頭を抱えたところだ。

クイックアクションが表示されるものについて、すべて繰り返す必要がある。PDF / MP4 / JPG / PNG / HEIF .... など全部です。

defaults 設定も探したのだけど、見つからなかった。もうむちゃくちゃ・・・なんだこのmacOSとかいうOSのアップデートは・・・

ファイル更新日時などの重要情報を見られない。

これ、まじどうなってるんだ。

これが、プレビューペインでクイックアクションが表示された状態。

f:id:takuya_1st:20210523124932p:plain:w240

これが、プレビューペインで、クイックアクションを消した状態。

f:id:takuya_1st:20210523124940p:plain:w240

ファイル情報がスクロールに隠れる。

ファイルの作成日や更新日が完全に隠れてしまう。画像の場合はExifなども隠れてしまう。Finderを再設計(キリッ)って、Appleのソフトウェア開発担当は何考えてんだろう。意味不明すぎて頭を抱える。

そろそろ、macOSをまどから投げ捨ててもいいかもしれません。

GMailのメール保護機能を使う。(有効期限・パスコードをつけて誤送信や情報漏洩防止)

GMailにはしばらく前から保護機能がついてます。

メールの時限機能をつけたり、送信後にアクセスを取り消したり、SMSコードがないと開けない(別経路送信)が使えます

保護機能では、「メールに有効期限」「SMSパスコード」が主に利用できますね。

利用は新規メール作成画面から行える。

f:id:takuya_1st:20210523120431p:plain:w300 f:id:takuya_1st:20210523120444p:plain:w300

f:id:takuya_1st:20210523120505p:plain:w400

ポイント

Gmail同士の場合と、外部のメールサーバーで取り扱いが異なります。

Gmail 同士の場合

保護モードのフラグ付きメールが送信されて、受信者のGmailから自動的に削除されるようです。

保護モードと表示されるメールが届きました。

通常のメールの場合

通常のメールの場合では、メールへのリンクが届きます。

リンク先を開いてメールを閲覧するようです。

f:id:takuya_1st:20210523120412p:plain:w400

動作が異なる注意点

Gmailと通常メアドで、メールの取り扱いが異なるので注意。

リンクを使うことですこしはリスクが軽減されるのであるが。受信者側のメールフィルタがうまく動作しないので、受信者に負担を強いることになると思う。

api から使えたらいいのだが・・・

自動でメール送信するソフトウェアやパスワードリマインドで使えれば良いな。と思って調べるが、今の所GmailのWEB以外に使う方法が見えたらない。自分のメール・ソフトウェアでも使えないと思われる。所詮はGoogleの独自仕様。

仮に使えたとしてもGoogleが気分一つでサービスを停止する可能性もあるし。知ってたら便利だけど仕組みやワークフローに組み込むほどの依存をする信頼性に至らない気はした。

workspace ( google apps ) の組織設定で一括できないのか

Workspace のGmail設定を見た限り、組織の全員にデフォルト設定するようなことはできなさそう。SMTPの経路設定で追加するしかなさそうですね。

メールのセキュリティ的な意味で

メールのセキュリティではまっさきにやることは暗号化と、大事なことは添付ファイルではなくリンクで送るようにすることですかね。

どうしても平文で贈りたいときに「選択肢」として知っておくのはいいですね。

参考資料

https://support.google.com/mail/answer/7674059?co=GENIE.Platform%3DDesktop&hl=ja

raspi ubuntu に docker をインストール

raspi 8GB でdocker を入れて遊ぶ

raspi 8GB が手元にあるので、docker とか snap とか lxc とか動かして遊ぶ。

raspbian で動かすとレポジトリで手こずるので、最初から aarch64 用にコンパイルされた ubuntu をインストールした.

インストール後のraspberry pi ubuntu の状態はこんな感じだった。

ubuntu のバージョンを見てみる。 aarch64 で64bit版だとわかる。

# cat /etc/os-release  && uname -a
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
Linux ubuntu 5.4.0-1035-raspi #38-Ubuntu SMP PREEMPT Tue Apr 20 21:37:03 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux

raspi ubuntu に docker をインストール

通常の ubuntu と同じ。docker のインストールに特に手順はなく通常のubuntuですね。

sudo snap install docker 
sudo groupadd docker
sudo usermod -aG docker $USER
sudo chown root:docker /var/run/docker.sock
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R
# sudo reboot 
systemctl restart docker.service

動作チェック

docker run で hello-world を動かしてみる。

takuya@raspi-ubuntu:~$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
256ab8fe8778: Pull complete
Digest: sha256:5122f6204b6a3596e048758cabba3c46b1c937a46b5be6225b835d091b90e46c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

動きますね。

ubuntu on docker raspi

raspi4 上の ubuntu で docker ubuntu も動かしておく

takuya@raspi-ubuntu:~$ docker run --rm ubuntu cat /etc/os-release
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
80bc30679ac1: Pull complete
c937c19c2d76: Pull complete
ba4ad2754376: Pull complete
Digest: sha256:adf73ca014822ad8237623d388cedf4d5346aa72c270c5acc01431cc93e18e2d
Status: Downloaded newer image for ubuntu:latest
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

快適だった

マジ快適に、サクッとインストール終わりますね。

raspi4 8GB + ubuntu は、メモリが多いので、あれこれにめっちゃ使いやすい。

aarch64 の docker ubuntu 速い。これクラスタリングしたくなる。

参考資料

https://linuxhandbook.com/docker-permission-denied/