それマグで!

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

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

git でローカルにブランチを作ってリモート(origin) にブランチをpush するまでの手順

ブランチをちょっとだけ使いこなす。

リモートに存在しないブランチを手元で作ってプッシュするまでの流れ。

レポジトリを持ってくる。

takuya@Desktop$ git clone git@example.com.:takuya/sample.git
takuya@Desktop$ cd sample/

現在のブランチを確認する。

リモートブランチを含め、現在あるブランチを確認する。

takuya@sample$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

ブランチを作成する。

ブランチを作成する(今回はリモートのmaster からブランチを作成)

takuya@sample$ git checkout -b  サンプルブランチ origin/master
Branch 'サンプルブランチ' set up to track remote branch 'master' from 'origin'.
Switched to a new branch 'サンプルブランチ'

ブランチが切られていることを確認する。

ブランチが切られていることを確認する。

takuya@sample$ git branch -a
  master
* サンプルブランチ
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
takuya@sample$ touch index.php
takuya@sample$ git add .

ローカルブランチへコミットする。

ブランチに変更を加えてみる。

takuya@sample$ git commit -m '作ったブランチへコミット'
[サンプルブランチ d5e9ee2] 作ったブランチへコミット
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 index.php
takuya@sample$ git push
Everything up-to-date

リモート(origin) にブランチを転送する。

コミットが出来たら、リモートに「ブランチ」を送信する。このときにリモートブランチが作成される。

takuya@sample$ git push origin サンプルブランチ
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 294 bytes | 294.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for サンプルブランチ, visit:
remote:   https://example.com/takuya/sample/merge_requests/new?merge_request%5Bsource_branch%5D=%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81
remote:
To example.com:takuya/sample.git
 * [new branch]      サンプルブランチ -> サンプルブランチ

ローカルブランチの状態を確認する。

remotes/origin/サンプルブランチ として、リモート(origin) にさっきのブランチが追加されてる。 これで、ローカルにあるブランチからリモートブランチ(新規作成)が出来たことが解る。

takuya@sample$ git branch -a
  master
*  サンプルブランチ
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/サンプルブランチ

ブランチが出来たら、マージ

ブランチが出来たら、次はマージするのですが、マージ作業をブラウザで出来るのがgithub のプルリクの強みだったりするのでいいよね。

ブランチ間のマージ

マージするときは master にマージしていくのが基本方針として、ブランチでの作業が少し進んでいる状態をmaster にマージする感じ。

master をチェックアウトして

takuya@sample$ git checkout master

サンプルブランチを取り込む

takuya@sample$ git  merge サンプルブランチ
Updating 460e6a0..2bf15e1
Fast-forward
 bashrc | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bashrc

取り込んだ、マージをリモートに送信する。

takuya@sample$ git push
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.

ローカルブランチを削除する。

takuya@sample$ git branch -d サンプルブランチ
Deleted branch サンプルブランチ (was 2bf15e1).

必要がなくなったリモートのブランチを消す。

リモートにブランチを削除するpush をする。

takuya@sample$ git push --delete origin サンプルブランチ
To example.com:takuya/sample.git
 - [deleted]         サンプルブランチ

まとめ

ローカルでブランチを作って、ブランチを送信できる

ブランチをマージするのは手元でやるのが基本。サーバー側でまとめて出来るのがgithub の魅力

リモートのブランチへの削除push が出来る

これで、帰宅時間が来たら帰宅時間ブランチを作ってpushすれば良いことが解る。

参考資料

ちょっと進んだGit, Githubの使い方~ブランチ活用編~ - nigoblog

シェルのalias されたコマンドの展開する - alias-expand-line

シェルのコマンドを展開したい。

composite 使おうとしたら、候補多すぎて面倒くさい。補完が補完にならないよね

takuya@~$ com<tab>
comm       command    compare    compgen    complete   compopt    composer   composite  compress   comsat

最初の3文字くらいで、展開されてほしい。 bashの補完で completion を書いても現在位置は置換できないし、alias で短縮しても履歴に元のコマンドを残したい。

alias してみてもうまくいかない。

alias すると、たしかに短くなるのだけど、履歴が汚れる。すげぇ面倒くさいわ。

alias comp=composite
history
997: comp
998: comp
999: comp

sysout<tab>System.out.println() になるような短縮(abbreviation)と補完(completion)をやりたいと思ってました。

alias-expand-line で解決する

ショートカットキー<ctl-alt-e> を押すと、展開される。これだ!

$ ll<ctl-alt-e>

こうなる

$ ls -lt 

これだ。

参考資料

https://superuser.com/questions/247770/how-to-expand-aliases-inline-in-bash

https://unix.stackexchange.com/questions/158038/non-interactive-shell-expand-alias

dockerのexpose のポートをlocalhostに限定する。

docker のポートのIPアドレスを限定したい。

expose したポートを、bind するときに、よく見る例がコレ

docker  run -p 80:80 ...

コレだと、0.0.0.0:80マッピングされる。グローバルアドレスにマッピングしてしまうのですよね。ちょっと先行き不安。

ローカル・ループバックに限定する

docker  run -p 127.0.0.1:80:80 ...

IPv6の ループバックはダメみたい

::1 はダメだった。悲しい。そのうちなんとかなるかも。

takuya@ubuntu01:~/docker-test$ docker-compose up -d
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.db.ports is invalid: Invalid port "::1:5432:5432", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]

docker-compose の場合

docker-compose の yml の場合はこう書くといいみたい。

    ports:
      - 127.0.0.1:5432:5432

なるほど、コレだとループバックだからiptables も考えなくていいから安心ですね。

参考資料

https://docs.docker.com/compose/compose-file/#ports

https://stackoverflow.com/questions/45109398/how-can-i-make-docker-compose-bind-the-containers-only-on-defined-network-instea

docker の mysql に sql を流し込んでデータベースを作ったり初期データをいれる

docker のmysql にデータを流し込みたい。

docker のmysql にデータ流し込む

docker exec -i 49723f3d7ed1  mysql -uroot -pPASWORD database_name < data.sql

exec のオプションに -it ではなく tty なしで -i だけでいい。

データベースにデータを投入するためだけに Dockerfile から COPY とか EXPOSE 3306 とか VOLUMEするのも面倒な話なので。

データベースにデータを投入したことを確認したい。

bash などを経由しなくても直接 tty を繋いで mysql のコンソールに繋いであげれば良いことが解る。

docker exec -it 49723f3d7ed1  mysql -uroot -pPASWORD database_name 

これでOK

docker-composeの管理が面倒なのでerb と makefileにした

docker-compose.yml が面倒くさい。

docker-compose は良く出来てるんだけど、環境変数だとか環境設定がめんどくさくないですか?

dockerfile から docker-compose.yml に進化して相当使いやすくなってるのはわかるんですね。

でも不便なものは不便。

コメントとか変数とか書きたい。

yml syntax チェックとかかしたい。

erb で変換することにしたら楽だった。

$ erb docker-compose.erb.yml | ruby -ryaml -e 'puts YAML.dump(YAML.load(ARGF.read()))' > docker-compose.yml

erb 変換して、その結果をrubyYAML に流し込んで整形することにした。 結構複雑なコメントとか書けるようになって嬉しかった。

makefile も併せて作った。

  • erb → yml に変換する
  • yml → docker 起動

この辺のワークフローをmakefile で作った。

name=php-apache-mysql
registry=takuya.registory.example.com/takuya/docker/$(name)

conf=docker-compose.yml
project-name=my$(name)
compose=docker-compose
cmd=$(compose) -f $(conf) --project-name $(project-name)

docker-compose.yml: docker-compose.erb.yml
    erb docker-compose.erb.yml | ruby -ryaml -e 'puts YAML.dump(YAML.load(ARGF.read()))' > $(conf)


.PHONY: all build run up down registory push clean

all: build

build:  docker-compose.yml
    $(cmd) build
run: build
    $(cmd) up
up: build
    $(cmd) up -d
down:
    $(cmd) down
kill-all:
    $(cmd) down

registry:
    @docker build -t $(registry) .
push: registry
    @docker push $(registry)
clean:
    -rm $(conf)

makefile 楽だわ。

gulp とかこういうビルドシステムは数あるけど、シンプルにやりたいことがぱぱっと出来るので 古き良きツールもまだまだ見捨てたらかわいそうだなって思った的な。

Dockerfileを作って試すときのコマンドが長いのでmakefileにした

dockerfile 書いたら負けってのは解る。

でも、dockerfile を書かないと、dockerのボリュームの切り分けタイミングや、entrypoint が理解できないし。

dockerfile を書いたことがないと docker hub から pull してきても使い方がわからない。

dockerfile を書いて実行するのが面倒くさい。

練習がてらに、dockerfileをたくさん書いたけど、コマンドが長くなってしまうので不便だよね。 dockerfile のサンプルをgithub で見ても殆どの人が、Rakefilemakefile を置いているので、やっぱりそうなんだと思った。

Makefile書いた

### dockerfile 単体時の設定

name = takuya-debian
.PHONY: all build run

all: build

build.log: ./Dockerfile
    @docker build -t $(name) .
    date +"%Y-%m-%d %H:%i:%s "> ./build.log

build: build.log

run:
    @docker run -it -d $(name)

## makefile 中での $() は $$() にする
login:
     @docker exec -it $$( docker ps -q  --filter 'ancestor=$(name)' -f 'status=running' )  bash


kill:
     @docker kill $$( docker ps -q  --filter 'ancestor=$(name)' -f 'status=running' ) 

makefile やコマンドを実行するときのポイント

  • 作成中の docker image にはかならず名前をつける
  • 名前を指定して実行する
  • 名前を使って終了する

docker ps の filter オプションを使う。

ubuntu のイメージを全て表示する

docker ps -a  --filter 'ancestor=ubuntu'

ubuntu のイメージで実行中のもの

docker ps -a  --filter 'ancestor=ubuntu' --filter 'status=running'

これらの他にもフィルタが在るのだけど。 docker ps をフィルタで使うことでとても楽に管理ができるようになった。

参考資料

https://docs.docker.com/engine/reference/commandline/ps/#filtering

debian ミラーをやめてさくらインターネットのミラーを頼る

debian ミラーって時々遅いので

自前のミラーを使って作ってるけど、それでも遅いので。

docker file が apt update 始まると apt ですごく時間が取られる

自分のミラーが見に行くところを変えていく

deb http://debian-mirror.sakura.ne.jp/debian/ stretch main
deb http://debian-mirror.sakura.ne.jp/debian/ stretch-updates main
deb http://debian-mirror.sakura.ne.jp/debian/ stretch/updates main

deb http://debian-mirror.sakura.ne.jp//debian/ stretch main stretch main
deb http://debian-mirror.sakura.ne.jp/debian/ stretch-updates main
deb http://debian-mirror.sakura.ne.jp/debian/ stretch/updates main

deb http://deb.debian.org/debian stretch main
deb http://deb.debian.org/debian stretch-updates main
deb http://security.debian.org stretch/updates main

コマンドで。

sed -i.bak  -s 's%http://deb.debian.org/debian%http://debian-mirror.sakura.ne.jp/debian//%g'  /etc/apt/sources.list \
#sed -i.bak  -s 's%http://security.debian.org/debian%http://debian-mirror.sakura.ne.jp/debian//%g'  /etc/apt/sources.list \

dockerはプロセスをaufs というかマウントで分離してくれるけど、docker pull 出来ないものを使おうとするととても不便だね。

ssh の秘密鍵をサーバー毎に指定して違う鍵に変えてログインする方法

SSH秘密鍵を使い分けたい。

git サーバーや自宅サーバーや、さくらVPSAmazonクラウド・・・そしてお仕事のサーバーなど SSHサーバーが多くなってくると鍵の管理が面倒になったりします。

サーバーごとに秘密鍵を変えることが出来る

ssh コマンドを使う際に、コマンドのオプションで鍵を指定することが出来る。

ssh -i  path/to/my/private_key.file myserver

でも面倒くさい・・・鍵を毎回指定するのが面倒だ。

そして ssh 設定をつかう github や SourceTreeなどのアプリケーションだと起動オプションで鍵を指定することが出来ない。

ssh 設定を使う

ssh には ~/ssh/config という設定ファイルがある。

このファイルを使えば、サーバー毎、鍵毎に設定と変えることが出来る。

Host 192.168.2.1
   Hostname 192.168.2.1
   IdentityFile ~/.ssh/router.key

SourceTreeなどのユーザーのSSH設定を読み込んでくれるアプリケーションを使う場合でも大丈夫

ssh 設定の例

複数の鍵とユーザー名を設定で切り分ける。

Host my-rooter
   Hostname 192.168.2.1
   IdentityFile ~/.ssh/router.key

Host my-rooter-root
   Hostname 192.168.2.1
   IdentityFile ~/.ssh/my-root.key
   user root

こう書いておけば、

takuya:~ @ ssh 192.168.2.1   # ~/.ssh/id_rsa かつ user takuya
takuya:~ @ ssh my-router     # ~/.ssh/router.key  かつ user takuya
takuya:~ @ ssh myrouter-root   # ~/.ssh/my-root.key かつ  user root

このように、サーバーの用途毎に名前をつけておき、ユーザー名や使う秘密鍵を指定することが出来る。

設定例

gitlab / github.com の場合

 Host github-work
   hostname github.com
   identityfile /users/takuya/.ssh/github-work

github /gitlab の場合は git@hostname/username/reponame となっていて、すべてのユーザーは git ユーザーでアクセスししている。 github 側で登録済みの公開鍵からユーザーを識別している感じ。

gitlab で使う鍵を指定する

 Host gitlab.example.com
   hostname gitlab.example.com
   identityfile ~/.ssh/gitlab-ssh-priv.key
 Host git.1.example.com
   hostname git.1.example.com
   identityfile ~/.ssh/git-priv.key

gitlab 毎に使う鍵を変えるなども出来る。

設定をまとめたい

hostalias を使う

Host mine
     HostAlias my01.example.com
     HostAlias my02.example.com
     HostAlias my03.example.com

こうしておけば、順番に試してくれたり。

他にできる設定

.ssh/config はかなりいろいろな設定ができる。

SSH接続時に同時にVPNを作成したり、 SSH接続時にポートを指定したり

詳しくは man

man ssh_config

参考書籍

OpenSSH

OpenSSH[実践]入門 Software Design plus

OpenSSH[実践]入門 Software Design plus

xargsでリダイレクト> を使う方法

xargs やfind exec でリダイレクトを使うには

sh を挟むのが覚えやすくて楽

sh -c ' cmd "{}"> out.txt '

find と xargs の例

find . | xargs -I@ sh -c ' echo "@" >> names.txt '
find . -exec  sh -c ' echo "{}" >> names.txt '

参考資料

https://stackoverflow.com/questions/845863/how-to-use-in-an-xargs-command

nginxで unix ドメイン socket をlisten してバックエンド専用に設定する。

nginx 使いまくり問題

docker やCDNとか使ってると、いくつのプロキシが挟まるんだよ。管理面倒くさいんだよ。って問題にぶち当たる。特にphp 関連。

browser → 企業・学校内プロキシ → CDN → docker ホスト nginx → dockerコンテナnginx → php-fpm

コレ全部が、SSLのデクリプトとエンクリプションや、TCPコネクションでsyn/ack してると思うとゾッとしない話ではない。そりゃhttp2でTCP節約が必要になるよねって感じる。

リバースプロキシから裏側はTCPを減らせるのでは。

docker ホスト nginx → dockerコンテナnginx → php-fpm

この部分がlocalhost:9000とかで待ち受けてるけど、全部unix ドメインソケットにしてしまえば、接続も管理も楽になるんじゃないかと。

nginx が unix sock で待ち受ける

ポートの管理とかTCPのコネクションが面倒くさいので、unix ソケットでnginx を動かしてみたらどうだろうか。 と思ったので試してみた。

nginx で設定してみる。

/etc/nginx/sites-enabled/default

server {
  #listen 80 default_server;
  #listen [::]:80 default_server;
  listen unix:/var/lib/nginx/backend.sock;
  access_log off;

  # SSL configuration
  #
  ##略
}

接続してみる

echo  'GET /' | nc -U /var/lib/nginx/backend.sock

nginx のunix:sock に応答する プロキシを 構成する。

リバースプロキシからバックエンドのnginxにunixソケットで接続できるようにする。

nginx:80 → nginx:sock に対応するものを作る。

upstream nginx-internal-sock {
    server unix:/usr/local/var/run/nginx-internal.sock;
}
server{

    listen 80;
    server_name 'www';
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Accept-Encoding "";
        proxy_pass http://nginx-internal-sock;
    }

}

または次のように書く

server{

  listen 80;
  server_name 'www';
  
  location / {
    proxy_pass http://unix:/usr/local/var/run/nginx-internal.sock; 
    ## ↑ http://unix:/ は記述ミスじゃなくて本当にこう書きます
  }

}

パスが違うのは、docker の起動時にボリュームでマッピングしてるから

-v /usr/local/var/run/:/var/lib/nginx/

socket ファイルを直接ボリュームマッピングすると socket がすでに存在しますと言われて起動できないので注意

何に使うの?

ポートの管理が面倒くさい。

docker で localhost:8001 / localhost:8002 / localhost:8003 と次々とnginxが占拠していくので何がなんだかわからなくなる。

とくに、nginx→(nginx+phpfpm) 間のリバースプロキシをすると管理が面倒くさいし、docker-composeのYAMLもだんだん増えてしまうので、ファイル名で扱うほうが楽かなかって思ったりしてる。ポート被らないし、ファイル名で識別できるし。ドメインソケットのほうがちょっとだけ速いし。

nginx-fpm をワンペアで扱う

apache+mod_php を使うのであれば、Apacheインスタンスを見ておけばいいが、 fastcgi+apachefastcgi+nginx にすると管理が面倒くさいのでソケットを volumeで外に出そうかなと。

アプリ側の設定 sites-enabled/myapp-php.nginx

upstream my-app-php-fpm {
   server unix:/usr/local/var/run/php-fpm/php-fpm.sock;
}
server{

    listen unix:/usr/local/var/run/my-app-nginx-internal.sock;
    root /var/www/html;

    location ~* \.php$ {
    fastcgi_pass  my-app-php-fpm;
    }

}

フロント側の設定。 sites-enabled/www.myapp.example.com.nginx

upstream nginx-internal-sock {
    server unix:/usr/local/var/run/my-app-nginx-internal.sock;
}
server{

    listen 80;
    server_name www.myapp.example.com;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Accept-Encoding "";
        proxy_pass http://nginx-internal-sock;

    }

}

こうしておけば、unix socket でバックエンドにつながるので、マシン上に大量にのっけてもポート管理が煩雑にならない。

pull して実行したらcomposer.yaml でポート被った!あああぅっ。ってならなくて済むんじゃないかなと。

apt-cacherで docker buildを速くする

docker build おそい。。。

Dockerfileを書くのが苦痛。ちょっと変えたらすぐに再構築が行われて、上手くキャッシュが効かないことが在る。

apt-update で待たされる。

apt-get update && apt upgrade && apt install がもう無理。1度や2度なら我慢するけど、10回実行する可能性があるならもう我慢できない。

キャッシュしようキャッシュ。

apt-cacher-ngでキャッシュしよう。

---
version: '2'
services:
  apt-cacher:
    container_name: proxies-apt-cacher
    image: sameersbn/apt-cacher-ng
    ports:
    - 3142:3142

docker-composer

docker-composer up -d

クライアント側にキャッシュ設定書こう。

dockerfile作ってるときだけつかう、APT設定ファイル書きましょう

Dockerfile

APT の設定をdocker ファイル作ってるときだけ cacher に向けて、build を考える速度で実行できるようにしておきたい。

apt-cacher-ng は debian でも ubuntu でもどちらでも受け付けてくれる万能選手なので優秀だ。

ubuntu の例。

FROM ubuntu:artful

MAINTAINER takuya_1st

## docker file 作成時の用途
RUN echo 'Acquire::HTTP::Proxy "http://172.17.0.1:3142";' >> /etc/apt/apt.conf.d/01proxy \
 && echo 'Acquire::HTTPS::Proxy "false";' >> /etc/apt/apt.conf.d/01proxy
RUN echo 'APT::Install-Recommends 0;' >> /etc/apt/apt.conf.d/01norecommends \
 && echo 'APT::Install-Suggests 0;' >> /etc/apt/apt.conf.d/01norecommends

## jaist にお願いする。
RUN sed -i.bak  -s 's%http://archive.ubuntu.com/ubuntu/%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g'  /etc/apt/sources.list
# RUN sed -i.bak  -s 's%http://security.ubuntu.com/ubuntu/%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g'  /etc/apt/sources.list

docker registry mirror と組み合わせる

ボトルネックを解消する。 docker 作ってて困るボトルネックは大きく4つ

  • apt install
  • docker pull
  • git clone
  • composer.phar install

これらをまとめて対策したいが、git clone と composer はちょっとめんどくさいので後回しにした。

docker pull を速くする、docker レジストリのミラー機能と組み合わせてまとめて起動しちゃう。

併せた。

---
version: '2'
services:
  apt-cacher:
    container_name: proxies-apt-cacher
    image: sameersbn/apt-cacher-ng
    ports:
    - 3142:3142
  docker-registry-proxy:
    container_name: proxies-docker-registry
    image: my.reg.example.com/docker-registry-proxy
    ports:
    - 5000:5000

これでだいぶ楽になった。

Dockerfile 書いたら負けって解ってるんだけど、docker pull で持ってきたイメージの中でapt update されてたりするのでだいぶ楽になった。思考を止めず、思考の速度でdockerfile 記述に一歩近づいた

関連資料

dockerのプロキシ(docker mirror registry)を設置してdocker hubからのpullを早くする - それマグで!

dockerのプロキシ(docker mirror registry)を設置してdocker hubからのpullを早くする

docker pull が遅い。

docker hub からのpull が遅い。docker-machine を作ったりvirtualbox で遊んでたりすると遅いんですよ。docker pullが

軽量化?いいやキャッシュが先だ

「お前のDockerイメージはまだ重い」とかDockerイメージの軽量化かダイエットに関する記事も多いんだけど、その時間も惜しい。dockerのコンテナの目的の一つが時間の節約だ。alpineで、秘伝のスープみたいなDockerfile を書くためのノウハウを蓄積する時間をダイエットしたいんだ。

まずは、ダイエットに時間掛けるより先にキャッシュでなんとかしてみよう。

apt-cacher みたいなのほしい。

docker の build 時や起動時の apt も遅かったり、docker build 時にすぐキャッシュが消えて apt が再実行されるので apt-cacher も速くするのに有効だった。

幾つものmachine で次々やってると docker hub の遅さも辛い。

docker hub mirror registry を起動して使う

Registry as a pull through cache | Docker Documentation に詳しいことが書いてあった。

設定は次の通り

  1. docker registry に mirroring の設定をする
  2. 手元のdocker に mirroring を使うように設定する。

docker registry に mirroring の設定をする

docker hub はログインしないと使えないので、ミラー用につかうレジストリが docker hub にログインできるように設定する。

proxy:
  remoteurl: https://registry-1.docker.io
  username: [username]
  password: [password]

これは面倒くさいので、docker イメージにした。

Dockerfile

FROM registry:2


RUN echo -ne "\
proxy:\n\
  remoteurl: https://registry-1.docker.io\n\
  username: takuyaXXXXX\n\
  password: PASSWORDn\
" >> /etc/docker/registry/config.yml

起動すら面倒くさい

起動すら面倒くさいので makefile 書いておいた。

make run

docker-compose は apt-cacheや HTTPプロキシと併せて起動するように別に書いた。

githubにおいておいた。

github.com

docker に設定する。

Docker for Mac に設定した。docker for Macが、ミラーを使ってくれるように設定した。

f:id:takuya_1st:20180109005345p:plain:w200

効果測定

じゃあ、これでどれくらい時短が出来るのか。

最後にどれくらい速くなる?測定だ

mirror のキャッシュが効く前(初回ロード)

takuya@docker-compose$ time docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
50aff78429b1: Pull complete
f6d82e297bce: Pull complete
275abb2c8a6f: Pull complete
9f15a39356d6: Pull complete
fc0342a94c89: Pull complete
Digest: sha256:fbaf303d18563e57a3c1a0005356ad102509b60884f3aa89ef9a90c0ea5d1212
Status: Downloaded newer image for ubuntu:latest

real    0m19.145s
user    0m0.047s
sys 0m0.043s

mirror でのキャッシュしたあと

docker rmi ubuntu でキャッシュを消して 再度取得してみる。

$ time docker rmi ubuntu
$ time docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu
50aff78429b1: Pull complete
f6d82e297bce: Pull complete
275abb2c8a6f: Pull complete
9f15a39356d6: Pull complete
fc0342a94c89: Pull complete
Digest: sha256:fbaf303d18563e57a3c1a0005356ad102509b60884f3aa89ef9a90c0ea5d1212
Status: Downloaded newer image for ubuntu:latest

real    0m4.883s
user    0m0.043s
sys 0m0.035s

比較

効果はバツグンだ。

導入前 導入後 時間差
19.145s 4.883s 14s

何処で使うのか。

イントラですよイントラ。

docker-machine が全部ミラー用を見るようにしておけば、virualbox などの docker-machineもバンバン使えるね。

参考資料

iptables の使い方 その1 ちょっとだけ理解して使うiptables

最低限のiptables 

余計なことをわすれて、最低限必要なiptablesに絞って、使い方を書いてみた。

iptables は複雑で面倒くさい。

はい、そのとおりです。iptables は面倒くさいので、ufw が作られています。 ufwiptables を目的別に管理してくれる人です。iptables を使うとありがちなミスや面倒な処理を ufw でやってくれるので、単なるポート別のアクセス制限ならufw を使ったほうが楽だし ufw 使うべきだと思います。

centos などには firewalld が用意されています。firewalld も iptables を自動化してくれるラッパーですが、個人的にはufw に比べてfirewalld は中途半端だと思います。

iptables が仕事をするところ

iptables はパケットの流れる箇所に仕込んで動作します。おもにフィルタや転送で使われる。ルーティングテーブルを通ってきたパケットをどうするかや、ルーティング前のパケットをどう処理するかなどに使う。

iptables で出来ること

家庭用のルーターにある機能がiptablesの機能だと思っておくと楽です。無線LANのAP機能はありません。

などが上げられます。

ルーティング機能

パケットはルーティングされる。iproute2 の ip-route機能で管理されるルーティング・テーブルに従ってパケットをルーティングを管理してくれる。

このルーティング機能にわりこんでフィルタを掛けるのが iptables と思えばだいたいわかると思う。 iptables 自体にルーティングテーブルの管理機能があるわけではないです。ルーティング・テーブルを管理する目的では ip-route を使います。。

パケットの流れ(IN・OUT)

インプットとアウトプットは、一番単純なパケットの流れ。

自分宛てに入ってきたパケットを書くポート番号のアプリケーションに渡す。

たとえば、次の図では、インプットアウトプットとプロセスとポートを示している。

ポート80で起動したApacheがにホストIP宛のパケットで80番宛のパケットが渡され、応答パケットはポート80から出ていく。

同様に、nginxが8080 で起動していても同じ。8080宛のパケットを受信したnginxが8080から応答パケットを返す。

f:id:takuya_1st:20180103205555p:plain

一番良く使う IN/OUT のフィルタの場所。

iptablesはインプット・アウトプットのパケットにフィルタを設置する。これが一番良く使われる。理解もしやすい。

フィルタで全てを捨て、必要な分だけ通す設定を書く。

ネットに書かれている殆どの設定の例はこれ。

f:id:takuya_1st:20180103205551p:plain

INPUT を全部捨てて、特定のプロセス宛を許可する例(SSH)

iptables -P INPUT DROP #1 
iptables -A INPUT -p tcp --dport 22 -j ACCEPT #2
  • 1: では、 INPUT のフィルタ設定し、全てデフォルト動作をは全て捨てる用にフィルタを設定。
  • 2: では、 INPUTのフィルタ追加し、TCPパケットで、且つ、宛先ポート22番、これを通すように設定。

デフォルト動作を設定するポリシは、フィルタにマッチしないパケットをどうするかの基本設定。

他にも80を許可したり

iptables -P INPUT DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

(わかりやすくポート番号だけを条件にしてる。

-p tcp  はナゼ必要?

これは、 「TCPパケットであること」を条件にする書き方。ナゼコレを書くのかというと。

ポート番号はTCPパケットに含まれる。そのためポートを知るには、tcp パケットの中身を調査しないとポートがわからない。SSHTCP以外のパケットはありえないので、TCPを条件に含めてる。

iptablesNICバイスを指定する。

iptables がややこしいのは、IPレイヤでのフィルタだけど、NICバイスで指定できる所。 IPパケット内容を見るとき、IPパケットが通ってきたネットワークカードを条件に追加できる。

もちろん必要なのだけど、初心者にはレイヤが混じるので理解できないかも??

iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT

eth0 を通ってきたパケットで、 tcp パケットであり、 宛先ポートが22番は ACCEPT して受け入れる

通常は使わなくても済むのだけれど、パケットがVPN経由だったりPPPoE経由だったりをNICで識別できるので便利に使える。

混乱しそうなポイント

iptablesを触り始めたときに混乱しそうなポイント。

iptablesはパケットを監視して、パケットを書き換えられるのでなんでも出来てしまうので、ざっくりと調べてるだけだと混乱してしまう。

そこで、混乱しそうなポイントにちょっとだけ触れておく。

最初のうちは、INPUT・OUTPUTだけをアレコレ設定してcurl したり ping して慣れていけばいいと思いました。

NIC条件

ネットワークインタフェース(NIC)はIPパケットではないが、iptablesで条件として使える。

ルーティングテーブルの存在

ルーティングテーブルはパケット宛先の条件として作用するが、iptablesの条件とは関係ない。 パケットが届かないときは、ルーティングテーブルが間違ってるのか、iptablesが間違っててパケットが捨てられるのかを考える。

フィルタ条件とデフォルトポリシー

フィルタ条件は先に書いた方からマッチされる。 一方で、ポリシーはマッチしないときに適用される。

ポリシーは最初に書いて、後からフィルタを記述しても大丈夫。

ただしインタラクティブシェルで行ってる場合は、ポリシーは最後にしないといきなりポリシーが適用されてその後のフィルタをを追加できなくなる。

IN・OUTフィルタに全く関係ないポイント

IN・OUTでパケットフィルタするだけの場合、

NAT関連のフィルタは全く勉強する必要がない。 FOWARDも勉強する必要がない。 チェイン知らなくても使えるので気にしなくていい。

なぜか、iptablesググると atmark IT のテンプレが上位に出てきてしまい、そのサイトでいきなりPREROUTING だの FILTERを同時に説明されるのでパニックになる。なので「知らなくても良いことは知らなくてもいい」と割り切ってしまったら楽になると思う。

ありがちなミス

デフォルトのパケットのポリシーを DROP にしておいて、パケットフィルタを初期化してしまう。

$ iptables -P INPUT DROP
$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ iptables -F # あっ

iptables -F でフィルタを初期化出来るので、ついつい iptables -F を打ってしまうが、デフォルトのポリシーが全部DROPなので、フィルタが無くなると、全てのパケットは破棄(drop)され、通信ができなくなってしまう。

ミスを防ぐ方法

iptables -L を実行したときの読み方を覚えておく。

takuya@ubuntu01:~$ sudo iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh

この表示の で INPUT (policy DROP) に注目する。デフォルトポリシーがDROPでフィルタがACCEPTで構成されている。

そのため、フィルタにマッチしないとき、デフォルトポリシーにあたって、DROPされる。フィルタにマッチしたものは通過する。

ポリシーをACCEPTのまま構成する。

今の例の全く反対の条件で書くことが出来る。

すなわち、全てACCEPTポリシー〜指定ポート以外全部拒否する。

逆のポリシーとかも記述が可能

not 条件を使ったフィルタ

SSH以外のパケットを全て拒否し、否定条件を使って同じことをする。

sudo iptables -P INPUT ACCEPT
sudo iptables -A INPUT -p tcp \! --dport 22 -j DROP

この場合は、iptables -L の結果が次のようになる。

takuya@ubuntu01:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere             tcp dpt:!ssh

同じことを実現するやり方だが、否定条件とド・モルガン則を使って構成すると上記のような条件になったりする。

ポリシーはiptables -F をする前に確認した方がいいよ。

ポリシーを理解する

左側が、デフォルトACCEPT、指定以外全部拒否、右側がデフォルトDROP、指定許可 ポリシを使わずに、フィルタだけで構成するなら左側もありかもしれない。

f:id:takuya_1st:20180103205559p:plain

ポリシーとフィルタ

ここまでの2例を使って、IN・OUTのポリシーとフィルタを理解が出来る。

以上が最初に覚えておくべき iptablesの設定でした。

組合せ。DROP条件を広く取って、指定ポートを追加した例。

ポリシーを使わずにポートを指定した例。

takuya@ubuntu01:~$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
DROP       tcp  --  anywhere             anywhere             tcp dpt:!ssh
takuya@ubuntu01:~$

DROP 以外の条件

DROPする以外にも選択肢がある。それがREJECT

REJECTを条件に書くと、CONECTION REFUSEDと即座に応答パケットが戻ってくるので、通信は届いていて、iptablesがダメ出ししたことが解るので、設定を作ってるときに、他の設定の切り分けに使えるので意外と使ってる。

REJECT を設定した例。

サーバー側で reject を設定した例

takuya@~$ ssh 192.168.56.101
takuya@ubuntu01:~$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     tcp  --  anywhere             anywhere             tcp dpt:!ssh reject-with icmp-port-unreachable
takuya@ubuntu01:~$

クライアントからパケットを送って接続を試みると、即座に応答パケットとしてREJECTが返ってくるので、わかりやすい。

takuya@~$ curl  192.168.56.101
curl: (7) Failed to connect to 192.168.56.101 port 80: Connection refused

git lfs でバイナリファイルをバージョン管理できるようにする

git レポジトリに大きめのファイルを突っ込みたい。

動画の素材ファイルや、画像の素材ファイルとか、Sketch とか figma のデータそのままとか、コンパイルしたExecをそのままとか、考えるの面倒くさいのでどっかに放り込んでいきたい。

google drive に放り込んでいたけど、バージョン管理に時間制限があって、30日前になる。かといってDropboxまで追加で契約すのも面倒くさい。Evernoteは添付ファイルに容量制限があるし。

git lfs でバイナリ用のバージョン管理をする。

git lfs がありまして、 git large file storage の略ですね。比較的大きめのファイルをまとめてツッコんでgit と連携させることが出来る github製のツールです。

github 以外でも bitbucketや gitlab で利用できます。

f:id:takuya_1st:20180103205002p:plain

使い方:クライアント

大きめのファイルをツッコんだら自動的にGit LFS になる。なんてことはない。このファイルはLFS管理しますよって設定が必要

なので、最初に このコマンドを突っ込む

git lfs install 

lfs のインストール

といっても、git lfs は git に同梱されておらず。別途インストールが必要。

brew install git-lfs

はじめの一歩

git lfs をインストール後に、レポジトリでlfs を有効にする、対象の拡張子を指定し設定する。そしてgitattributesを追加してcommit する。

git clone URL
cd REPO
git lfs install                #
git lfs track '*.psd'     # ここがlfs 特有の箇所
git add .gitattributes  #
git commit -m 'my commit comment'
git push origin master

git lfs install でlfs 初期設定

lfs install すると .git ディレクトリ内部に、lfs の管理フォルダが生成される

takuya@sample001$ find  .git/
/Users/takuya/.bin/find .git/ -mindepth 1 -not -iwholename '*/.git/*'
.git/config
.git/description
.git/HEAD
.git/info
.git/info/exclude
## ↓この辺が作られる
.git/lfs
.git/lfs/objects
.git/lfs/objects/logs
.git/lfs/tmp
.git/lfs/tmp/objects
.git/objects
.git/objects/info
.git/objects/pack
.git/refs
.git/refs/heads
.git/refs/tags

git lfs track でLFSの管理にするファイルのパターンをしてい、その設定が gitattributeに記述されるので、それを追加する。

git lfs track '*.rar' をした場合

gitattributes ファイルに、どのファイルをLFS対象にするか設定が書かれる。

takuya@sample001$ grep rar -R   .
./.gitattributes:1:*.rar filter=lfs diff=lfs merge=lfs -text

すでに設定があるので、重複したtrackも検出される。

takuya@sample001$ git lfs track '*.rar'
"*.rar" already supported

あとは commit

gitattributes も忘れずにコミットしないとね。

gitlab の場合

gitlab で git lfs を使う場合は、 lfs.url を追加しておく必要があった

git clone URL
cd REPO
git lfs install                
git config --add lfs.url https://example.com/takuya/sample01.git/info/lfs
git lfs track '*.psd'     
git add .gitattributes  
git commit -m 'my commit comment'
git push origin master

git lab のレポジトリURLの末尾に、 reponame.git/info/lfs を加えたものを追加した。

gitlab 側の設定

omni gitlab CE側では LFSを受け取れるように設定する必要があった。

### Git LFS
gitlab_rails['lfs_enabled'] = true
gitlab_rails['lfs_storage_path'] = "/var/opt/gitlab-lfs" 

lfs_storage_pathは自分で指定しておく必要がある。 reconfigure した時に、生成されパーミッションが設定された。

LargeFileが入ってくるところなので、それなりに安心して置いて置ける場所がいいと思う。

ディレクトリ設定に注意が必要だった。 ディレクトリは、gitlab レポジトリと別に設定できるので、管理対象として認識する必要がある。

ディレクトリを追加してるので、バックアップや移動時やDocker起動してるときに面倒だな

2018-01-03 追記

git config --add lfs.url は無くても動いた。

アイティメディアIDがパスワード12文字以下

アイティメディアIDを登録したらこんなことに。

f:id:takuya_1st:20171228144225p:plain

なぜ、パスワード文字数の上限が在るんでしょうか。

  • パスワード文字数の上限が在る
  • → 固定長でデータベースが設計されてる
  • → → AESかなにかでEncryptするなど原文まま保存している

つまり、ハッシュ化してないんじゃないかと。最近多いのかなぁ。パスワードといえばハッシュだと信じてた私が間違ってるんでしょうか?