drawthe.netを使ってシステム構成図を書く
drawthe.netを使いたい理由
美しい構成図といえばInteropを思い出しますよね。
参考:Interopのネットワーク図を描くエンジニア:Geekなぺーじ
美しく整った図は人を魅了しますし、機能性にも優れています。システム構成図はさまざまな人(開発エンジニア、保守・運用エンジニア、オペレータなど)から参照される資料なので、なるべく美しく整った状態であるべきと考えます。しかし、Visoやdraw.ioでこのような図を書こうと思うと本当に大変ですし、人の能力に依存します。また、Visoやdraw.ioで書かれた美しい構成図は、メンテナンス性が悪く、1ピクセルの配置のために常にズームインとズームアウトを繰り返すこととなります。
前書きが長くなりましたが、drawthe.netを使いたい理由は上記背景から下記3つとなります。
- 誰でも整った図を書けるツールがほしい
- メンテナンス性に優れたツールがほしい
- 変更に対する差分がわかるようにしたい
これらを満たすツールがdrawthe.netだったわけです。
drawthe.netをdockerイメージで使ってみる
先述のデモサイトでも十分使えますが、興味本位から自環境内にdockerで建ててみます。
dockerイメージを探す
dockerイメージを探してみましたが、公式はなく、個人配布もほとんどありませんでした。
$ docker search drawthenet
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
thomasbridge/drawthenet My drawthe.net images 1
こちらのリポジトリは1年以上にdockerhubに上げられたものですが、十分使えそうです。
とりあえずpullして
$ docker pull thomasbridge/drawthenet:nginx
イメージを確認して
$ docker images thomasbridge/drawthenet:nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
thomasbridge/drawthenet nginx 72163b5fff23 15 months ago 237MB
runします。80番ポートをローカルの4000番ポートに紐づけてみました。
$ docker run --rm -d -p 4000:80 thomasbridge/drawthenet:nginx
0f21cb1d9cf90bd858c0dd9afe6893f8b7660f8c8ac1523fad2a1de9f4909f0d
起動を確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0f21cb1d9cf9 thomasbridge/drawthenet:nginx "nginx -g 'daemon of…" 53 seconds ago Up 52 seconds 0.0.0.0:4000->80/tcp objective_saha
問題なくアクセスできました。
docker buildしてみる①
なんとなく、自前のdockerイメージをつくってみます。
分析
先のdockerイメージ(thomasbridge/drawthenet:nginx)のベースOSはDebianのようです。
$ docker exec 0f21cb1d9cf9 cat /etc/*-release
cat: /etc/lsb-release: No such file or directory
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
history
を見てみるとnginxをビルドして、git cloneでdrawthe.netのリポジトリを引っ張ってきているだけのようです。
$ docker history thomasbridge/drawthenet:nginx
IMAGE CREATED CREATED BY SIZE COMMENT
72163b5fff23 15 months ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 15 months ago /bin/sh -c git clone https://github.com/cidr… 27.8MB
<missing> 15 months ago /bin/sh -c rm index.html 50x.html 0B
<missing> 15 months ago /bin/sh -c apt-get update && apt-get install… 99.4MB
<missing> 15 months ago /bin/sh -c #(nop) WORKDIR /usr/share/nginx/h… 0B
<missing> 15 months ago /bin/sh -c #(nop) MAINTAINER Thomas Bridge … 0B
<missing> 19 months ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 19 months ago /bin/sh -c #(nop) STOPSIGNAL SIGTERM 0B
<missing> 19 months ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 19 months ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
<missing> 19 months ago /bin/sh -c set -x && apt-get update && apt… 54.1MB
<missing> 19 months ago /bin/sh -c #(nop) ENV NJS_VERSION=1.15.12.0… 0B
<missing> 19 months ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.12… 0B
<missing> 20 months ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 20 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 20 months ago /bin/sh -c #(nop) ADD file:4fc310c0cb879c876… 55.3MB
省略なしでヒストリーを見たい場合は --no-trunc
をつけてください。
$ docker history --no-trunc thomasbridge/drawthenet:nginx > history.txt
実践
とりあえず作ってみます。ベースイメージは nginx
を使い、シンプルに git clone
するだけにします。
$ mkdir ~/project/drawthenet-test
$ cd ~/project/drawthenet-test
$ git clone https://github.com/cidrblock/drawthe.net.git
Cloning into 'drawthe.net'...
remote: Enumerating objects: 13309, done.
remote: Total 13309 (delta 0), reused 0 (delta 0), pack-reused 13309
Receiving objects: 100% (13309/13309), 20.31 MiB | 1.61 MiB/s, done.
Resolving deltas: 100% (4359/4359), done.
$ vi Dockerfile
$ cat Dockerfile
FROM nginx:latest
MAINTAINER Masayoshi Tohna
WORKDIR /usr/share/nginx/html
COPY ./drawthe.net/* /usr/share/nginx/html/
では、ビルドします。
$ docker build --no-cache -t drawthenet-test:0.1.1 .
Sending build context to Docker daemon 28.61MB
Step 1/4 : FROM nginx:latest
---> daee903b4e43
Step 2/4 : MAINTAINER Masayoshi Tohna
---> Running in ce257ba2fda5
Removing intermediate container ce257ba2fda5
---> b982bb23d361
Step 3/4 : WORKDIR /usr/share/nginx/html
---> Running in 16aaead7564f
Removing intermediate container 16aaead7564f
---> 8f47acfb0bbc
Step 4/4 : COPY ./drawthe.net/* /usr/share/nginx/html/
---> 363c26bea7ac
Successfully built 363c26bea7ac
Successfully tagged drawthenet-test:0.1.1
イメージを確認。
$ docker images drawthenet-test:0.1.1
REPOSITORY TAG IMAGE ID CREATED SIZE
drawthenet-test 0.1.1 363c26bea7ac 54 seconds ago 161MB
起動します。
$ docker run -d -p 4001:80 drawthenet-test:0.1.1
94de3748233e3191b787f1365043c5f428a5c6b768c4cf8eb46716672643d5d2
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94de3748233e drawthenet-test:0.1.1 "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 0.0.0.0:4001->80/tcp exciting_elgamal
残念。表示が崩れてしまいました。
docker buildしてみる②
調べてみたところ、nodeが必要なようです。ベースイメージをnodeにして、nginxを導入する流れにしてみます。
$ cat Dockerfile
FROM node:6.17.0-alpine
MAINTAINER Masayoshi Tohna
RUN apk update && apk --no-cache add nginx
WORKDIR /usr/share/nginx/html
RUN rm -f *
COPY ./drawthe.net/* /usr/share/nginx/html/
CMD nginx -g "daemon off;"
ビルドします。
$ docker build --no-cache -t drawthenet-test:0.1.2 .
Sending build context to Docker daemon 28.61MB
Step 1/7 : FROM node:6.17.0-alpine
---> 7c9d8e1567b1
Step 2/7 : MAINTAINER Masayoshi Tohna
---> Running in a400a53db3ee
Removing intermediate container a400a53db3ee
---> 77145f10a4f0
Step 3/7 : RUN apk update && apk --no-cache add nginx
---> Running in d8caf9efce35
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
v3.8.5-65-g097f0358a9 [http://dl-cdn.alpinelinux.org/alpine/v3.8/main]
v3.8.5-37-gf06ffe835a [http://dl-cdn.alpinelinux.org/alpine/v3.8/community]
OK: 9565 distinct packages available
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/2) Installing pcre (8.42-r0)
(2/2) Installing nginx (1.14.2-r2)
Executing nginx-1.14.2-r2.pre-install
Executing busybox-1.28.4-r3.trigger
OK: 7 MiB in 17 packages
Removing intermediate container d8caf9efce35
---> 71cfb2217c02
Step 4/7 : WORKDIR /usr/share/nginx/html
---> Running in 31de29b6bb59
Removing intermediate container 31de29b6bb59
---> 253552423e40
Step 5/7 : RUN rm -f *
---> Running in 1f610efda890
Removing intermediate container 1f610efda890
---> 71adc1a7fdf6
Step 6/7 : COPY ./drawthe.net/* /usr/share/nginx/html/
---> 2dade49c7640
Step 7/7 : CMD nginx -g "daemon off;"
---> Running in 47c324aff65c
Removing intermediate container 47c324aff65c
---> c143b7a0dd05
Successfully built c143b7a0dd05
Successfully tagged drawthenet-test:0.1.2
起動しません。
あ、nginxのconfいじる必要あり?今日はここまで。
※最終的にはアイコンをAWSの最新のものに入れ替えるところまでやる予定。
docker buildしてみる③
Ubuntuベースでdockerイメージを作りなおす。
試行錯誤の結果、drawthenetはnode v6.x以前でないと動かない。
参考:【2019年6月版】fs.writeFile したら ERR_INVALID_CALLBACK ですって - Qiita
古い node を動かすには nvm でインストールすると良いらしい。
参考:Ubuntu でapt を使用してNode.js をインストールする3 つの方法(Ubuntu 15.04, Ubuntu 14.04.2 LTS) - Qiita
Qiitaの手順でやると nvm を実行するときにターミナルの再読み込みを要求されて、乗り越え方がわからなかった。
ということで、以下のサイトを参考に行った。
参考:node.js — dockerにnvmをインストールします
FROM ubuntu:latest
MAINTAINER Masayoshi Tohna
# Replace Shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# make sure apt is up to date
RUN apt update --fix-missing
RUN apt install -y curl
RUN apt install -y build-essential libssl-dev
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 6.17.1
# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
RUN node -v
最終的に nginx:latest
をベースに作成。無事、ブラウザで呼び出すことができた。
FROM nginx:latest
MAINTAINER Masayoshi Tohna
# Replace Shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# make sure apt is up to date
RUN apt update --fix-missing
RUN apt install -y curl
RUN apt install -y build-essential libssl-dev
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 6.17.1
# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
RUN node -v
WORKDIR /usr/share/nginx/html
COPY drawthe.net .
ビルドは以下の通り。
$ docker build --no-cache -t drawthenet:debian-nginx-node6.17.1 .
起動は以下の通り。
docker run --rm -d -p 4000:80 drawthenet:debian-nginx-node6.17.1
ここまでの成果物をGitHubリポジトリに公開した。
oresama-lab/drawthenet-personal
アイコンを変更する
drawthe.net
のリポジトリに含まれているアイコンは古いので、最新のAWSアイコンに変更したい。
AWS公式が配布している アセットパッケージ
をダウンロードして svg 画像を抜き出す。
参考:AWS シンプルアイコン - AWS アーキテクチャーセンター | AWS
drawthenet リポジトリの build/images/aws
のアイコンを置き換える。
※古いアイコンも使いたければ置いといてもOK。
これで、docker コンテナを再ビルドしてあげれば新しいアイコンを使えるようになる。アイコンの指定は拡張子なしのファイル名でOK。
BEFORE | AFTER |
---|---|
一応、テキストも残しておく。
icons:
dns: {<<: *iconDefaults, icon: net_route53_hostedzone, x: 2, y: 3 }
lb: {<<: *iconDefaults, icon: cmpt_elasticloadbalancing, y: "-1" }
server1: {<<: *iconDefaults, icon: cmpt_ec2_instance, x: "-1", y: "-1" }
server2: {<<: *iconDefaults, icon: cmpt_ec2_instance, x: "+1" }
server3: {<<: *iconDefaults, icon: cmpt_ec2_instance, x: "+1" }
icons:
dns: {<<: *iconDefaults, icon: arch_route53_16, x: 2, y: 3 }
lb: {<<: *iconDefaults, icon: arch_elasticloadbalancing_16, y: "-1" }
server1: {<<: *iconDefaults, icon: arch_ec2_16, x: "-1", y: "-1" }
server2: {<<: *iconDefaults, icon: arch_ec2_16, x: "+1" }
server3: {<<: *iconDefaults, icon: arch_ec2m5n_32, x: "+1" }
もし、入れ替えた画像がうまく反映されない場合は drawthe.net/build/images/build_list.js
をコンテナ内で実行してあげると反映される模様。この build_list.js
が node v7.x 以降だと動かないので、今回作った Dockerfile では v6.17.1 で固定している。
使いたいアイコンを整理する
とりあえず、AWS公式アイコン集から svg を一つの階層にまとめる。
$ ~/project/drawthenet/aws-icons
$ find AWS-Architecture-Service-Icons_20200911/ -type f -name "*.svg" -exec cp {} ~/project/drawthenet/aws-icons \;
svg だけで全部で897ファイルあるようです。
Arch_AWS-Amplify-Console_16.svg
みたいなファイル名なので、すべてのファイルに共通している先頭の Arch_
を rename コマンドで削除する。
$ rename s/Arch_// *.svg
複数サイズあると邪魔なので、デカサイズだけ残す。
$ for i in $(ls | grep -E "_16|_32|_48"); do rm -f $i; done
ここまでで228ファイルまで減少。
_64
という文言も不要なのでリネームしてしまいます。
$ rename s/_64// *.svg
ということで、クレンジング完了。※邪魔なので拡張子も除去した
AWS-Amplify-Console
AWS-Apache-MXNet
AWS-App-Config
AWS-App-Mesh
AWS-App-Wizard
AWS-AppSync
AWS-Application-Discovery-Service
AWS-Artifact
AWS-Auto-Scaling
AWS-Backint-Agent
AWS-Backup
AWS-Batch
AWS-Bottlerocket
AWS-Braket
AWS-Budgets
AWS-Certificate-Manager
AWS-Chatbot
AWS-Cloud-Development-Kit
AWS-Cloud-Trail
AWS-Cloud9
AWS-CloudEndure-Disaster-Recovery
AWS-CloudEndure-Migration
AWS-CloudFormation
AWS-CloudHSM
AWS-CloudMap
AWS-CodeArtifact
AWS-CodeCommit
AWS-CodeDeploy
AWS-CodePipeline
AWS-Command-Line-Interface
AWS-Compute-Optimizer
AWS-Config
AWS-Console-Mobile-Application _16
AWS-Console-Mobile-Application _32
AWS-Console-Mobile-Application _48
AWS-Console-Mobile-Application
AWS-Control-Tower
AWS-Cost-Explorer
AWS-Cost-and-Usage-Report
AWS-Data-Exchange
AWS-Data-Pipeline
AWS-Data-Sync
AWS-Database-Migration
AWS-Deep-Composer
AWS-Deep-Learning-AMIs
AWS-Deep-Learning-Containers
AWS-Deep-Lense
AWS-Deepracer
AWS-Device-Farm
AWS-Direct-Connect
AWS-Directory-Service
AWS-EC2-Image-Builder
AWS-Elastic-Beanstalk
AWS-Elemental-Appliances-&-Software
AWS-Elemental-Link
AWS-Elemental-MediaConnect
AWS-Elemental-MediaConvert
AWS-Elemental-MediaLive
AWS-Elemental-MediaPackage
AWS-Elemental-MediaStore
AWS-Elemental-MediaTailor
AWS-Express-Workflow
AWS-Fargate
AWS-Firewall-Manager
AWS-Global-Accelerator
AWS-Glue
AWS-Ground-Station
AWS-IQ
AWS-Identity-and-Access-Management
AWS-IoT-1-Click
AWS-IoT-Analytics
AWS-IoT-Button
AWS-IoT-Core
AWS-IoT-Device-Defender
AWS-IoT-Device-Management
AWS-IoT-Events
AWS-IoT-Greengrass-Core
AWS-IoT-SiteWise
AWS-IoT-Things-Graph
AWS-Key-Management-Services
AWS-Lake-Formation
AWS-Lambda
AWS-License-Manager
AWS-Local-Zones
AWS-Managed-Services
AWS-Management-Console
AWS-Migration-Hub
AWS-Nitro-Enclaves
AWS-OpsWorks
AWS-Organizations
AWS-Outposts
AWS-Parallel-Cluster
AWS-Personal-Health-Dashboard
AWS-PrivateLink
AWS-Professional-Services
AWS-Resources-Access-Manager
AWS-RoboMaker
AWS-SageMaker-Ground-Truth
AWS-SageMaker
AWS-Secrets-Manager
AWS-Security-Hub
AWS-Server-Migration-Service
AWS-Serverless-Application-Repository
AWS-Service-Catalog
AWS-Shield
AWS-Simple-Email-Service
AWS-Simple-Notification-Service
AWS-Simple-Queue-Service
AWS-Single-Sign-On
AWS-Site-to-Site-VPN
AWS-Snowball-Edge
AWS-Snowball
AWS-Snowcone
AWS-Snowmobile
AWS-Step-Functions
AWS-Storage-Gateway
AWS-Sumerian
AWS-Support
AWS-Systems-Manager
AWS-TensorFlow-on-AWS
AWS-Textract
AWS-ThinkBox-Deadline
AWS-ThinkBox-Frost
AWS-ThinkBox-Krakatoa
AWS-ThinkBox-Sequoia
AWS-ThinkBox-Stoke
AWS-ThinkBox-XMesh
AWS-Tools-and-SDK
AWS-Training-Certification
AWS-Transfer-Family
AWS-Transit-Gateway
AWS-Trusted-Advisor
AWS-VPN
AWS-WAF
AWS-Wavelength
AWS-Well-Architect-Tool
AWS-WorkLink
AWS-WorkSpaces
AWS-X-Ray
Alexa-For-Business
Amazon-API-Gateway
Amazon-App-Stream
Amazon-Application-Auto-Scaling
Amazon-Athena
Amazon-Augmented-AI-A2I
Amazon-Aurora
Amazon-Chime
Amazon-Cloud-Directory
Amazon-CloudFront
Amazon-CloudSearch
Amazon-CloudWatch
Amazon-CodeBuild
Amazon-CodeGuru
Amazon-Codestar
Amazon-Cognito
Amazon-Comprehend
Amazon-Connect
Amazon-Detective
Amazon-DocumentDB
Amazon-DynamoDB
Amazon-EC2-Auto-Scaling
Amazon-EC2-M5n
Amazon-EC2-R5n
Amazon-EC2
Amazon-EMR
Amazon-ElastiCache
Amazon-Elastic-Block-Store
Amazon-Elastic-Container-Kubernetes
Amazon-Elastic-Container-Registry
Amazon-Elastic-Container-Service
Amazon-Elastic-File-System
Amazon-Elastic-Inference
Amazon-Elastic-Transcoder
Amazon-Elasticsearch-Service
Amazon-EventBridge
Amazon-FSx-For-WFS
Amazon-FSx-for-Lustre
Amazon-FSx
Amazon-Forecast
Amazon-Fraud-Detector
Amazon-FreeRTOS
Amazon-GameLift
Amazon-Glacier
Amazon-GuardDuty
Amazon-Inspector
Amazon-Interactive-Video
Amazon-Kendra
Amazon-Keyspaces
Amazon-Kinesis-Data-Analytics
Amazon-Kinesis-Data-Streams
Amazon-Kinesis-Firehose
Amazon-Kinesis-Video-Streams
Amazon-Kinesis
Amazon-Lex
Amazon-Lightsail
Amazon-Lumberyard
Amazon-MQ
Amazon-Macie
Amazon-Managed-Blockchain
Amazon-Managed-Streaming-for-Kafka
Amazon-Neptune
Amazon-Neuron-ML-SDK
Amazon-Personalize
Amazon-Pinpoint-Journey
Amazon-Pinpoint
Amazon-Polly
Amazon-Quantum-Ledger-Database
Amazon-QuickSight
Amazon-RDS-for-VMware
Amazon-RDS
Amazon-Redshift
Amazon-Redshiftct
Amazon-Rekognition
Amazon-Route-53
Amazon-S3-Standard
Amazon-Timestream
Amazon-Transcribe
Amazon-Translate
Amazon-Virtual-Private-Cloud
Amazon-WorkDocs
Amazon-WorkMail
Elastic-Load-Balancing
Infrequent-Access-Storage-Class
Reserved-Instance-Reporting
Savings-Plans
Standard-Storage-Class
TorchServe
VMware-Cloud-on-AWS
アーキテクチャとリソースでフォルダが別れていることに気がついた。
アーキテクチャはさっきのでOKなので、リソースをなんとかする。
$ find AWS-Architecture-Resource-Icons_20200911/ -type f -name "*.svg" -exec cp {} ./res \;
$ for i in $(ls | grep _Dark); do rm -f $i; done