目次

,

gentoo で mastodon インスタンスを立ち上げてみた

ドメインを持っていて、固定 IP を持っていて、お手軽にサーバーを作れる仮想環境を持っていて……こんな面白そうなこと、手を出さない理由はないですよね?

[17/05/08 追記] ちょっとこの雑記、全体的にフェイク入れすぎですね。この記事で立ち上げた mastodon インスタンスは tekkadon で現在も稼働しています。まぁその……ものすごい勢いで弱小インスタンスですがw

仮想ホストをつくる。

うちの環境ではとりあえず、いつもどおり virt-clone で、仮想サーバーを作ります。このクローン元のゲスト OS は、stage1 から作って vi とか gentoolkit とか gdisk とか e2fsprogs とか、あとはうちの環境で便利にするために net-snmp とか ntpd とか、そのへんの必要最低限のパッケージだけ詰めて、定期的にアップデートしているクローニング元の専用の仮想サーバーなので、ほぼほぼスッピンの gentoo だと思ってください。いや、余計なもの入れていない分だけスッピン以下かもしれませんが……

docker 環境を作る

ちまちまと gentoo なりの構築をしていきましょう。なにはなくとも docker 環境ですね。こういう時は相変わらず Gentoo Wiki が頼りになります。このとおりにやりましょう。

kernel オプションを設定する

wiki に書いてあるとおり設定したんですが、docker を emerge した時に不足している項目が結構出てきました。

 * Messages for package app-emulation/docker-17.03.1:

 *   CONFIG_USER_NS:     is not set when it should be.
 *   CONFIG_BLK_DEV_THROTTLING:  is not set when it should be.
 *   CONFIG_CFQ_GROUP_IOSCHED:   is not set when it should be.
 *   CONFIG_IP_VS:       is not set when it should be.
 *   CONFIG_IP_VS_PROTO_TCP:     is not set when it should be.
 *   CONFIG_IP_VS_PROTO_UDP:     is not set when it should be.
 *   CONFIG_IP_VS_NFCT:  is not set when it should be.
 *   CONFIG_IP_VS_RR:    is not set when it should be.
 *   CONFIG_VXLAN:       is not set when it should be.
 *   CONFIG_XFRM_USER: is optional for secure networks
 *   CONFIG_IPVLAN:      is not set when it should be.
 *   CONFIG_MACVLAN:     is not set when it should be.
 *   CONFIG_DUMMY:       is not set when it should be.
 * Please check to make sure these options are set correctly.
 * Failure to do so may cause unexpected problems.

ここには、これらも加味したコンフィグを残しておきます。使用している kernel は 4.9.16-gentoo です。 kernel のコンパイル手順は kernel コンパイル に大体書いてあります。

General setup 以下はこんな感じに……

General setup  --->
    [*] POSIX Message Queues
    -*- Control Group support  --->
        [*]   Memory controller
        [*]     Swap controller
        [*]       Swap controller enabled by default
        [*]   IO controller
        [ ]     IO controller debugging
        [*]   CPU controller  --->
            [*]   Group scheduling for SCHED_OTHER
            [*]     CPU bandwidth provisioning for FAIR_GROUP_SCHED
            [*]   Group scheduling for SCHED_RR/FIFO
        [*]   PIDs controller
        [*]   Freezer controller
        [*]   HugeTLB controller
        [*]   Cpuset controller
        [*]     Include legacy /proc/<pid>/cpuset file
        [*]   Device controller
        [*]   Simple CPU accounting controller
        [*]   Perf controller
        [ ]   Example controller

    -*- Namespaces support
        [*]   UTS namespace
        -*-   IPC namespace
        [*]   User namespace
        [*]   PID Namespaces
        -*-   Network namespace

Control Group support の下は wiki と比べて結構名前が違っていたので、とりあえず全部チェックしときました……

次は block layer です。

-*- Enable the block layer  --->
    [*]   Block layer bio throttling support
    IO Schedulers  --->
	    [*]   CFQ Group Scheduling support

続いて Networking support です。

-*- Networking support  --->
    Networking options  --->
        <*> Transformation user configuration interface
        [*] Network packet filtering framework (Netfilter)  --->
            [*]   Advanced netfilter configuration
            <*>     Bridged IP/ARP packets filtering  # depends on 802.1d Ethernet Bridging
            <*>   IP virtual server support  --->
                [*]   TCP load balancing support
                [*]   UDP load balancing support
                <*>   round-robin scheduling
                [*]   Netfilter connection tracking
            Core Netfilter Configuration  --->
                <*> Netfilter connection tracking support
                <*>   "addrtype" address type match support
                <*>   "conntrack" connection tracking match support
            IP: Netfilter Configuration  --->
                <*> IPv4 connection tracking support (required for NAT)
                -*- IPv4 NAT
                -*-   IPv4 masquerade support
                <*> IP tables support (required for filtering/masq/NAT)
                <*>   Packet filtering
                <*>   iptables NAT support
                <*>     MASQUERADE target support
                <*>     NETMAP target support
                <*>     REDIRECT target support
        <*> 802.1d Ethernet Bridging
        [*] QoS and/or fair queueing  --->
            <*>   Control Group Classifier
        [*] L3 Master device support
        [*] Network priority cgroup
        -*- Network classid cgroup

こちらも結構名前や場所が wiki に記載のあるものと変わっています。また、Bridged IP/ARP packets filtering802.1d Ethernet Bridging<*> にしないと現れないため、注意です。

Device Drivers です。

Device Drivers  --->
    [*] Multiple devices driver support (RAID and LVM)  --->
        <*>   Device mapper support
        <*>     Thin provisioning target
    
    [*] Network device support  --->
        [*]   Network core driver support
        <*>     Dummy net driver support
        <*>     MAC-VLAN support
        <*>     IP-VLAN support
        <*>     Virtual eXtensible Local Area Network (VXLAN)
        <*>     Virtual ethernet pair device
  
    Character devices  --->
        [*] Enable TTY
        [*]   Unix98 PTY support

wiki に書いてある Support multiple instances of devpts は設定が見つからないのですが、menuconfig の中で / で検索してみるとどうもデフォルトで有効になっているようです。

Symbol: DEVPTS_MULTIPLE_INSTANCES [=DEVPTS_MULTIPLE_INSTANCES]
Type  : unknown
    Selected by: GENTOO_LINUX_INIT_SYSTEMD [=y] && GENTOO_LINUX [=y] && GENTOO_LINUX_UDEV [=y]

どんどんいきます。File system です。

File systems  --->
    <*> Overlay filesystem support
        Pseudo filesystems  --->
            [*] HugeTLB file system support

最後に Security options いきます。

Security options  --->
    -*- Enable access key retention support
    [*]   Enable register of persistent per-UID keyrings
    <M>   ENCRYPTED KEYS
    [*]   Diffie-Hellman operations on retained keys

全部設定したら make してインストールして reboot します。

# make -j5 && make modules_install
# mount /boot
# cp arch/x86_64/boot/bzImage /boot/kernel-4.9.16-gentoo.20170422.01
# grub-mkconfig -o /boot/grub/grub.cfg
# systemctl reboot

docker を emerge する

とりあえずやってみましょう。ちなみに gentoo での docker 環境は /var/lib/docker に構築されるようです。コンテナを追加していくと結構なサイズになってくるので、予め別のパーティションを切っておいたり、lv を割り当てたりするのも良いかと思います。……後述しますが、ここを 2GB にしておいたら導入の過程で1回でパンクしましたw そんなわけなので今は余裕を持って 8GB にしています。

# emerge -av app-emulation/docker

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] dev-lang/go-1.7.5:0/1.7.5::gentoo  USE="(-gccgo)" 61453 KiB
[ebuild  N     ] dev-libs/libaio-0.3.110::gentoo  USE="-static-libs {-test}" ABI_X86="(64) -32 (-x32)" 42 KiB
[ebuild  N     ] dev-util/boost-build-1.62.0-r1::gentoo  USE="-examples -python {-test}" PYTHON_TARGETS="python2_7" 0 KiB
[ebuild  N     ] app-emulation/docker-runc-1.0.0_rc2_p20170308::gentoo  USE="seccomp (-apparmor) -hardened" 549 KiB
[ebuild  N     ] dev-libs/libassuan-2.4.3-r1::gentoo  USE="-static-libs" 547 KiB
[ebuild  N     ] virtual/perl-Scalar-List-Utils-1.420.200_rc-r1::gentoo  0 KiB
[ebuild  N     ] dev-db/sqlite-3.17.0:3::gentoo  USE="readline -debug -doc -icu -secure-delete -static-libs -tcl {-test} -tools" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] app-emulation/docker-proxy-0.8.0_p20161111::gentoo  2101 KiB
[ebuild  N     ] dev-libs/libksba-1.3.5-r1::gentoo  USE="-static-libs" 607 KiB
[ebuild  N     ] dev-libs/npth-1.3::gentoo  USE="-static-libs" 290 KiB
[ebuild  N     ] app-eselect/eselect-lib-bin-symlink-0.1.1::gentoo  45 KiB
[ebuild  N     ] dev-go/sanitized-anchor-name-0_pre20151027::gentoo  2 KiB
[ebuild  N     ] dev-libs/boost-1.62.0-r1:0/1.62.0::gentoo  USE="nls threads -context -debug -doc -icu -mpi -python -static-libs -tools" ABI_X86="(64) -32 (-x32)" PYTHON_TARGETS="python2_7 python3_4 (-python3_5)" 0 KiB
[ebuild  N     ] virtual/perl-MIME-Base64-3.150.0-r2::gentoo  0 KiB
[ebuild  N     ] virtual/perl-libnet-3.80.100_rc::gentoo  0 KiB
[ebuild  N     ] virtual/perl-Digest-SHA-5.950.100_rc-r1::gentoo  0 KiB
[ebuild  N     ] virtual/perl-Digest-MD5-2.540.0-r2::gentoo  0 KiB
[ebuild  N     ] net-misc/curl-7.53.0::gentoo  USE="ipv6 ssl -adns -http2 -idn -kerberos -ldap -metalink -rtmp -samba -ssh -static-libs {-test} -threads" ABI_X86="(64) -32 (-x32)" CURL_SSL="openssl -axtls -gnutls (-libressl) -mbedtls -nss -polarssl (-winssl)" 2552 KiB
[ebuild  N     ] app-emulation/containerd-0.2.5_p20170308::gentoo  USE="seccomp -hardened" 998 KiB
[ebuild  N     ] app-arch/libarchive-3.2.2-r1:0/13::gentoo  USE="acl bzip2 e2fsprogs iconv lzma threads xattr zlib -expat (-libressl) -lz4 -lzo -nettle -static-libs" ABI_X86="(64) -32 (-x32)" 5331 KiB
[ebuild  N     ] dev-libs/libuv-1.10.2:0/1::gentoo  USE="-static-libs" ABI_X86="(64) -32 (-x32)" 1050 KiB
[ebuild  N     ] dev-perl/Error-0.170.240::gentoo  USE="{-test}" 31 KiB
[ebuild  N     ] dev-perl/Digest-HMAC-1.30.0-r1::gentoo  8 KiB
[ebuild  N     ] dev-perl/Net-SSLeay-1.800.0::gentoo  USE="-examples (-libressl) -minimal {-test}" 387 KiB
[ebuild  N     ] app-eselect/eselect-pinentry-0.7::gentoo  0 KiB
[ebuild  N     ] dev-go/blackfriday-1.2_p20150720::gentoo  67 KiB
[ebuild  N     ] sys-block/thin-provisioning-tools-0.4.1::gentoo  USE="{-test}" 183 KiB
[ebuild  N     ] sys-fs/lvm2-2.02.145-r2::gentoo  USE="readline systemd thin udev (-clvm) (-cman) -corosync -device-mapper-only -lvm1 -lvm2create_initrd -openais (-selinux) (-static) (-static-libs)" 0 KiB
[ebuild  N     ] dev-go/go-md2man-1.0.3::gentoo  4 KiB
[ebuild  N     ] dev-util/cmake-3.7.2::gentoo  USE="ncurses -doc -emacs -qt5 -system-jsoncpp {-test}" 7190 KiB
[ebuild  N     ] dev-perl/Authen-SASL-2.160.0-r1::gentoo  USE="-kerberos" 45 KiB
[ebuild  N     ] dev-perl/IO-Socket-SSL-2.24.0::gentoo  USE="-idn" 205 KiB
[ebuild  N     ] app-crypt/pinentry-0.9.7-r1::gentoo  USE="ncurses -caps -emacs -gnome-keyring -gtk -qt4 -qt5 -static" 423 KiB
[ebuild  N     ] sys-process/tini-0.13.2::gentoo  USE="args static" 28 KiB
[ebuild  N     ] app-crypt/gnupg-2.1.18::gentoo  USE="bzip2 gnutls nls readline smartcard -doc -ldap (-selinux) -tofu -tools -usb -wks-server" 6161 KiB
[ebuild  N     ] dev-perl/Net-SMTP-SSL-1.30.0::gentoo  USE="{-test}" 3 KiB
[ebuild  N     ] dev-vcs/git-2.10.2::gentoo  USE="blksha1 curl gpg iconv nls pcre perl python threads webdav -cgi -cvs -doc -emacs -gnome-keyring -gtk -highlight (-libressl) -mediawiki -mediawiki-experimental (-ppcsha1) -subversion {-test} -tk -xinetd" LINGUAS="-bg -ca -de -fr -is -it -ko -pt_PT -ru -sv -vi -zh_CN" PYTHON_TARGETS="python2_7" 4397 KiB
[ebuild  N     ] app-emulation/docker-17.03.1::gentoo  USE="container-init device-mapper seccomp (-apparmor) -aufs -btrfs -hardened -overlay -pkcs11" 7592 KiB

Total: 38 packages (38 new), Size of downloads: 102273 KiB

The following USE changes are necessary to proceed:
 (see "package.use" in the portage(5) man page for more details)
# required by app-emulation/docker-17.03.1::gentoo[container-init]
# required by app-emulation/docker (argument)
>=sys-process/tini-0.13.2 static

Would you like to add these changes to your config files? [Yes/No] y

……多いですねw

Autounmask changes successfully written.

 * IMPORTANT: config file '/etc/portage/package.use/zz-autounmask' needs updating.
 * See the CONFIGURATION FILES and CONFIGURATION FILES UPDATE TOOLS
 * sections of the emerge man page to learn how to update config files.

あ。そかそか。 package.use が追加されたので dispatch-confuse-new して反映しておきます。

# dispatch-conf

--- /etc/portage/package.use/zz-autounmask      2017-04-22 21:12:50.523014740 +0900
+++ /etc/portage/package.use/._cfg0001_zz-autounmask    2017-04-22 21:15:59.095746952 +0900
@@ -1 +1,3 @@
-# package.use
\ No newline at end of file
+# package.use# required by app-emulation/docker-17.03.1::gentoo[container-init]
+# required by app-emulation/docker (argument)
+>=sys-process/tini-0.13.2 static

>> (1 of 1) -- /etc/portage/package.use/zz-autounmask
>> q quit, h help, n next, e edit-new, z zap-new, u use-new
   m merge, t toggle-merge, l look-merge: u

そして気を取り直して。

# emerge -av app-emulation/docker

emerge が完了した時点で、不足している kernel オプションがあると指摘してくれます。

 * Messages for package app-emulation/docker-17.03.1:

 *   CONFIG_USER_NS:     is not set when it should be.
 *   CONFIG_BLK_DEV_THROTTLING:  is not set when it should be.
 *   CONFIG_CFQ_GROUP_IOSCHED:   is not set when it should be.
 *   CONFIG_IP_VS:       is not set when it should be.
     :
     :

その場合はもう一度 kernel を作り直します。make menuconfig の中で / キーで検索モードに入れるので “CONFIG_USER_NS” とか検索して必要な設定を1つずつ潰します。

もしくは、こんなツールもあるようです。

# /usr/share/docker/contrib/check-config.sh
info: reading kernel config from /proc/config.gz ...

Generally Necessary:
- cgroup hierarchy: properly mounted [/sys/fs/cgroup]
- CONFIG_NAMESPACES: enabled
- CONFIG_NET_NS: enabled
- CONFIG_PID_NS: enabled
- CONFIG_IPC_NS: enabled
- CONFIG_UTS_NS: enabled
- CONFIG_CGROUPS: enabled
- CONFIG_CGROUP_CPUACCT: enabled
- CONFIG_CGROUP_DEVICE: enabled
- CONFIG_CGROUP_FREEZER: enabled
- CONFIG_CGROUP_SCHED: enabled
- CONFIG_CPUSETS: enabled
- CONFIG_MEMCG: enabled
- CONFIG_KEYS: enabled
- CONFIG_VETH: enabled
- CONFIG_BRIDGE: enabled
- CONFIG_BRIDGE_NETFILTER: enabled
- CONFIG_NF_NAT_IPV4: enabled
- CONFIG_IP_NF_FILTER: enabled
- CONFIG_IP_NF_TARGET_MASQUERADE: enabled
- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE: enabled
- CONFIG_NETFILTER_XT_MATCH_CONNTRACK: enabled
- CONFIG_NETFILTER_XT_MATCH_IPVS: missing
- CONFIG_IP_NF_NAT: enabled
- CONFIG_NF_NAT: enabled
- CONFIG_NF_NAT_NEEDED: enabled
- CONFIG_POSIX_MQUEUE: enabled

Optional Features:
- CONFIG_USER_NS: enabled
- CONFIG_SECCOMP: enabled
- CONFIG_CGROUP_PIDS: enabled
- CONFIG_MEMCG_SWAP: enabled
- CONFIG_MEMCG_SWAP_ENABLED: enabled
- CONFIG_LEGACY_VSYSCALL_EMULATE: enabled
- CONFIG_BLK_CGROUP: enabled
- CONFIG_BLK_DEV_THROTTLING: enabled
- CONFIG_IOSCHED_CFQ: enabled
- CONFIG_CFQ_GROUP_IOSCHED: enabled
- CONFIG_CGROUP_PERF: enabled
- CONFIG_CGROUP_HUGETLB: enabled
- CONFIG_NET_CLS_CGROUP: enabled
- CONFIG_CGROUP_NET_PRIO: enabled
- CONFIG_CFS_BANDWIDTH: enabled
- CONFIG_FAIR_GROUP_SCHED: enabled
- CONFIG_RT_GROUP_SCHED: enabled
- CONFIG_IP_VS: enabled
- CONFIG_IP_VS_NFCT: enabled
- CONFIG_IP_VS_RR: enabled
- CONFIG_EXT4_FS: enabled
- CONFIG_EXT4_FS_POSIX_ACL: enabled
- CONFIG_EXT4_FS_SECURITY: enabled
- Network Drivers:
  - "overlay":
    - CONFIG_VXLAN: enabled
      Optional (for encrypted networks):
      - CONFIG_CRYPTO: enabled
      - CONFIG_CRYPTO_AEAD: enabled
      - CONFIG_CRYPTO_GCM: missing
      - CONFIG_CRYPTO_SEQIV: missing
      - CONFIG_CRYPTO_GHASH: missing
      - CONFIG_XFRM: enabled
      - CONFIG_XFRM_USER: enabled
      - CONFIG_XFRM_ALGO: enabled
      - CONFIG_INET_ESP: missing
      - CONFIG_INET_XFRM_MODE_TRANSPORT: missing
  - "ipvlan":
    - CONFIG_IPVLAN: enabled
  - "macvlan":
    - CONFIG_MACVLAN: enabled
    - CONFIG_DUMMY: enabled
- Storage Drivers:
  - "aufs":
    - CONFIG_AUFS_FS: missing
  - "btrfs":
    - CONFIG_BTRFS_FS: missing
    - CONFIG_BTRFS_FS_POSIX_ACL: missing
  - "devicemapper":
    - CONFIG_BLK_DEV_DM: enabled
    - CONFIG_DM_THIN_PROVISIONING: enabled
  - "overlay":
    - CONFIG_OVERLAY_FS: enabled
  - "zfs":
    - /dev/zfs: missing
    - zfs command: missing
    - zpool command: missing

Limits:
- /proc/sys/kernel/keys/root_maxkeys: 1000000

必ずしも必要ではない optional なものも含めて、docker に関連する kernel オプションとその有効/無効を列挙してくれるようです。ちなみにこのツールは kernel オプションで “General setup → Kernel .config support” を有効にしていないと動作しないと思います。

# grep 'CONFIG_IKCONFIG' /usr/src/linux/.config
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y

起動してみる

細かい設定は置いておくとして、とりあえず起動できるか確認してみます。

# systemctl start docker
# docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Sat Apr 22 22:18:59 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Sat Apr 22 22:18:59 2017
 OS/Arch:      linux/amd64
 Experimental: false

とりあえず、無事に起動できたようです。

btrfs とか device-mapper とか

wiki ではこのあと btrfs の使い方なんかが書いてあるようですが、とりあえずは device-mapper のままで行こうと思います。これは gentoo で docker を emerge した時のデフォルトのようです。

docker-compose を emerge する

もうひとつ、あとで必要となるパッケージを emerge します。

# emerge -av docker-compose
These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] dev-python/six-1.10.0::gentoo  USE="-doc {-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 29 KiB
[ebuild  N     ] dev-python/pyasn1-0.1.8::gentoo  USE="-doc" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 74 KiB
[ebuild  N     ] dev-python/enum34-1.1.6::gentoo  USE="-doc" PYTHON_TARGETS="python2_7 (-pypy) (-pypy3)" 40 KiB
[ebuild  N    ~] dev-python/ipaddress-1.0.18::gentoo  PYTHON_TARGETS="python2_7 -pypy" 32 KiB
[ebuild  N     ] dev-python/texttable-0.8.3::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-python3_5)" 9 KiB
[ebuild  N     ] dev-python/pyyaml-3.12::gentoo  USE="-examples -libyaml" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 248 KiB
[ebuild  N    ~] dev-python/colorama-0.3.7::gentoo  USE="-examples" PYTHON_TARGETS="python2_7 python3_4 -pypy -pypy3 -python3_5 -python3_6" 25 KiB
[ebuild  N     ] dev-python/docopt-0.6.2-r1::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5)" 26 KiB
[ebuild  N    ~] dev-python/cached-property-1.3.0::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 -python3_5" 10 KiB
[ebuild  N     ] dev-python/chardet-2.3.0::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 161 KiB
[ebuild  N     ] dev-python/py-1.4.30::gentoo  USE="-doc {-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 188 KiB
[ebuild  N     ] dev-python/idna-2.0::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 132 KiB
[ebuild  N     ] dev-python/ply-3.9::gentoo  USE="-examples" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 148 KiB
[ebuild  N     ] dev-python/PySocks-1.5.6::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-python3_5) (-python3_6)" 9 KiB
[ebuild  N     ] dev-python/backports-1.0::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-python3_5) (-python3_6)" 3 KiB
[ebuild  N     ] dev-python/webcolors-1.5::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 30 KiB
[ebuild  N     ] dev-python/functools32-3.2.3::gentoo  PYTHON_TARGETS="python2_7 (-pypy)" 31 KiB
[ebuild  N     ] dev-python/strict-rfc3339-0.6::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 17 KiB
[ebuild  N     ] dev-python/rfc3986-0.4.1::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 22 KiB
[ebuild  N     ] dev-python/vcversioner-2.16.0.0::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 9 KiB
[ebuild  N     ] dev-python/backports-ssl-match-hostname-3.5.0.1-r1::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-python3_5) (-python3_6)" 6 KiB
[ebuild  N    ~] dev-python/dockerpty-0.4.1::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 -python3_5" 20 KiB
[ebuild  N     ] dev-python/jsonschema-2.5.1-r2::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 50 KiB
[ebuild  N     ] dev-python/pycparser-2.14::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 219 KiB
[ebuild  N    ~] dev-python/docker-pycreds-0.2.1::gentoo  PYTHON_TARGETS="python2_7 python3_4 -python3_5" 8 KiB
[ebuild  N     ] virtual/python-ipaddress-1.0-r1::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 0 KiB
[ebuild  N     ] dev-python/websocket-client-0.37.0::gentoo  USE="-examples" PYTHON_TARGETS="python2_7 python3_4 (-python3_5) (-python3_6)" 190 KiB
[ebuild  N     ] dev-python/cffi-1.9.1:0/1.9.1::gentoo  USE="-doc {-test}" PYTHON_TARGETS="python2_7 python3_4 (-python3_5) (-python3_6)" 398 KiB
[ebuild  N     ] dev-python/cryptography-1.7.1::gentoo  USE="(-libressl) {-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 411 KiB
[ebuild  N     ] dev-python/pyopenssl-16.2.0::gentoo  USE="-doc -examples {-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 164 KiB
[ebuild  N     ] dev-python/ndg-httpsclient-0.4.0::gentoo  PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 24 KiB
[ebuild  N     ] dev-python/urllib3-1.16::gentoo  USE="-doc {-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-python3_5) (-python3_6)" 176 KiB
[ebuild  N     ] dev-python/requests-2.11.1::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 (-pypy) (-pypy3) (-python3_5) (-python3_6)" 475 KiB
[ebuild  N    ~] dev-python/docker-py-2.2.1::gentoo  USE="-doc {-test}" PYTHON_TARGETS="python2_7 python3_4 -python3_5" 171 KiB
[ebuild  N    ~] app-emulation/docker-compose-1.12.0::gentoo  USE="{-test}" PYTHON_TARGETS="python2_7 python3_4 -python3_5" 194 KiB

Total: 35 packages (35 new), Size of downloads: 3732 KiB

The following keyword changes are necessary to proceed:
 (see "package.accept_keywords" in the portage(5) man page for more details)
# required by docker-compose (argument)
=app-emulation/docker-compose-1.12.0 ~amd64
# required by dev-python/docker-py-2.2.1::gentoo[python_targets_python2_7]
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/ipaddress-1.0.18 ~amd64
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/cached-property-1.3.0 ~amd64
# required by dev-python/docker-py-2.2.1::gentoo
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/docker-pycreds-0.2.1 ~amd64
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/colorama-0.3.7 ~amd64
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/dockerpty-0.4.1 ~amd64
# required by app-emulation/docker-compose-1.12.0::gentoo
# required by docker-compose (argument)
=dev-python/docker-py-2.2.1 ~amd64

Would you like to add these changes to your config files? [Yes/No] y

……いやまた多いですけどね。

あとここでは package.keywords の追加設定を求められるので、先と同じく dispatch-conf して適用します。 ~amd64 とか gentoo っぽくなってきましたw

mastodon 環境を構築する

さてさて。それでは mastodon を作ってみます。CentOS7でmastodonを建てる こちらの記事を参考にしています。ありがとうございます。

github から最新の mastodon を clone する

まずこの作業で最新の mastdon 環境を自分のサーバーに持ってきます。

# cd /path/to/mydon
# git clone https://github.com/tootsuite/mastodon.git

git コマンドを発行した場所に mastdon というディレクトリが作成されて、そこに mastodon 環境が展開されます。現時点(2017/04/22)では、60MB ぐらいのサイズになるようですね。

ちなみに git コマンドは、docker を emerge した時に引っ張られて一緒にインストールされていました。

.env.production の設定

mastodon の設定をやっていきます。

# cp /path/to/mydon/.env.production.sample /path/to/mydon/.env.production
# vi /path/to/mydon/.env.production

とりあえずこんな感じでいいのでしょうか。

--- .env.production.sample      2017-04-22 23:37:35.000000000 +0900
+++ .env.production     2017-04-22 23:54:13.000000000 +0900
@@ -3,14 +3,14 @@ REDIS_HOST=redis
 REDIS_PORT=6379
 # REDIS_DB=0
 DB_HOST=db
-DB_USER=postgres
-DB_NAME=postgres
-DB_PASS=
+DB_USER=<ヒミツUser>
+DB_NAME=<ヒミツDb>
+DB_PASS=<ヒミツPass>
 DB_PORT=5432
 
 # Federation
-LOCAL_DOMAIN=example.com
+LOCAL_DOMAIN=mastodon.manimani.cc
 
 # Use this only if you need to run mastodon on a different domain than the one used for federation.
 # Do not use this unless you know exactly what you are doing.

参照している記事と違うことをやっているのは ssl の設定ですね。うちは nginx が reverse proxy しているので ssl終端はそこに任せて mastodon 自体は non-ssl http で良しとしました。 違いますね。docker 環境だからなのかどうかはわからないですが、そもそも reverse proxy 前提で作られているみたいです。ここで設定する LOCAL_HTTPS は、true にしておかないと……例えば2段階認証のために送信されてくるメールの url が http://mastodon.manimani.cc みたいにになってしまいます。ssl 終端は nginx なりでやる前提で、mastodon 環境は多分 non-ssl http でやる前提での https の設定です。true にしましょう。

「鍵」の作成

次は docker-compose なるコマンドを流します。

# docker-compose run --rm web rake secret

途中まで調子よく走ってたんですが、エラーで落ちました。

Step 6/9 : COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
 ---> 8708eaeb970c
Removing intermediate container 11d024cfb20f
Step 7/9 : RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*
 ---> Running in c48f7ea05f2b
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.4/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.167438ca.tar.gz: No such file or directory
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.4/community: temporary error (try again later)
WARNING: Ignoring APKINDEX.a2e6dac0.tar.gz: No such file or directory
fetch https://nl.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz
ERROR: https://nl.alpinelinux.org/alpine/edge/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.65bdaf85.tar.gz: No such file or directory
OK: 21 MiB in 29 packages
WARNING: Ignoring APKINDEX.167438ca.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.a2e6dac0.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.65bdaf85.tar.gz: No such file or directory
WARNING: The repository tag for world dependency 'nodejs@edge' does not exist
WARNING: The repository tag for world dependency 'nodejs-npm@edge' does not exist
WARNING: The repository tag for world dependency 'imagemagick@edge' does not exist
ERROR: Not committing changes due to missing repository tags. Use --force to override.
ERROR: Service 'web' failed to build: The command '/bin/sh -c echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*' returned a non-zero code: 255

ん~…… http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz に接続できないみたいですが、手元のブラウザーから叩けばちゃんと接続できるんですよね。はて。

docker コンテナに入ってみる

とりあえず、いま起動しているコンテナに入ってみようと思います。

# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
dfc72598a287        redis:alpine        "docker-entrypoint..."   59 minutes ago      Up 27 seconds       6379/tcp            mastodon_redis_1
2b853c0d87a4        postgres:alpine     "docker-entrypoint..."   59 minutes ago      Up 58 minutes       5432/tcp            mastodon_db_1

え~と……

# docker exec -it mastodon_db_1 '/bin/bash'
bash-4.3# 

おぉ~入れた。

bash-4.3# ping dl-cdn.alpinelinux.org
ping: bad address 'dl-cdn.alpinelinux.org'

……エラーで落ちたコンテナそのものではないけど、これもしかして外に出られないんじゃ? bridge とかその辺のハナシでしょうか?

ものすごくハマりましたが……

3日ぐらいハマりました。iptables に -j LOG を仕込んでみたり、色々なインターフェイスに tcpdump を仕掛けてみたり。

とりあえず色々やってみた限りでは、どうも ping でもなんでも全てのパケットが masquerade で出て行って、ちゃんと応答も返ってきているんですが、ホストのインターフェイスから bridge に渡されていないようです。

iptables にログを仕掛けても戻りパケットに関するログは何ひとつでていなかったので、それ以前の問題で……というわけで結果的にたどり着いたのが systemd-networkd の設定でした。

[Network]
IPForward=kernel

# man systemd.network にも書いてありますね。

       IPForward=
           Configures IP forwarding for the network interface. If enabled
           incoming packets on the network interface will be forwarded to
           other interfaces according to the routing table. Takes either a
           boolean argument, or the values "ipv4" or "ipv6", which only
           enables IP forwarding for the specified address family, or
           "kernel", which preserves existing sysctl settings. This controls
           the net.ipv4.conf.<interface>.forwarding and
           net.ipv6.conf.<interface>.forwarding sysctl options of the network
           interface (see ip-sysctl.txt[1] for details about sysctl options).
           Defaults to "no".

           Note: unless this option is turned on, or set to "kernel", no IP
           forwarding is done on this interface, even if this is globally
           turned on in the kernel, with the net.ipv4.ip_forward,
           net.ipv4.conf.all.forwarding, and net.ipv6.conf.all.forwarding
           sysctl options.

いや # echo 1 > /proc/sys/net/ipv4/ip_forward とか # sysctl net.ipv4.conf.all.forwarding とかの記事は検索にたくさん引っかかったんですが、まさかその設定を使うかどうかの設定が systemd にあったとは……とほほ。このへんはチマチマと設定を手書きする gentoo のハマりどころかも知れませんね。

気を取り直して docker-compose

# docker-compose run --rm web rake secret
 :
 :
Step 7/9 : RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*
 ---> Running in 8cc3d7affb98
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
fetch https://nl.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz
OK: 21 MiB in 29 packages
(1/90) Installing binutils-libs (2.26-r0)
(2/90) Installing binutils (2.26-r0)
(3/90) Installing gmp (6.1.0-r0)
(4/90) Installing isl (0.14.1-r0)
(5/90) Installing libgomp (5.3.0-r0)
(6/90) Installing libatomic (5.3.0-r0)
(7/90) Installing libgcc (5.3.0-r0)
(8/90) Installing mpfr3 (3.1.2-r0)
(9/90) Installing mpc1 (1.0.3-r0)
 :
 :

コケたところも無事通過しました。

(17/20) Purging mpc1 (1.0.3-r0)
(18/20) Purging mpfr3 (3.1.2-r0)
(19/20) Purging libxml2-dev (2.9.4-r2)
(20/20) Purging sqlite-libs (3.13.0-r0)
Executing busybox-1.24.2-r13.trigger
OK: 161 MiB in 99 packages
ERROR: Service 'web' failed to build: devmapper: Error mounting '/dev/mapper/docker-254:49-16385-85019299032f4db9faba8646327bbb9fb34736b8a54cccd05a793c108e43dd56' on '/var/lib/docker/devicemapper/mnt/85019299032f4db9faba8646327bbb9fb34736b8a54cccd05a793c108e43dd56': device or resource busy

またコケましたwww ……orz

今度の原因は

……って。あ。

# df -h /var/lib/docker
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdd1       2.0G  1.9G     0 100% /var/lib/docker

ダサい。ダサすぎます……イタいですw ディスクを 8GB まで追加してリトライします。

やっと完走しました

やっとこさ、最後まで完走できました。

 :
 :
Removing intermediate container 1b4fa3e749e7
Step 9/9 : VOLUME /mastodon/public/system /mastodon/public/assets
 ---> Running in 33f62532701b
 ---> 6e02c6dd9be8
Removing intermediate container 33f62532701b
Successfully built 6e02c6dd9be8
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
2xxxxxxxxxxxxxxxxxxxxbxxxxxxxxxxxxxxxxxxxx5xxxxxxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxexxxxxxxxxxxxxxxxxxxx9xxxxxxxxxxxxxxxxxxxxb8

……そういえば「鍵」ってハナシでしたね。この最後の行にでてる文字列が「鍵」でしょうか。もう1回やってみます。

# docker-compose run --rm web rake secret
bxxxxxxxxxxxxxxxxxxxx9xxxxxxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxaxxxxxxxxxxxxxxxxxxxxexxxxxxxxxxxxxxxxxxxx9xxxxxxxxxxxxxxxxxxxxc6

2回目は過程をすっ飛ばしてあっという間に文字列だけ出て終了しました。これが「鍵」で間違いなさそうです。3回目も実行して .env.production に追記します。

# vi .env.production

PAPERCLIP_SECRET SECRET_KEY_BASE OTP_SECRET の3つですね。

メールの設定

あと .env.production でコメントアウトされていないのはメールまわりの設定ですね。

SMTP_SERVER=ip.addr.mail.svr
SMTP_PORT=25
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=mastodon@donotreply.manimani.cc

ここはとりあえず自前のメールサーバーを設定しておけば良いでしょう。

コンテナ起ち上げ

ここからが本番でしょうか?

web 環境の構築?

なんとなく、画面に流れたログを見る感じでは web 環境のコンテナを作っている……のかな。

# docker-compose build
redis uses an image, skipping
db uses an image, skipping
Building web
Step 1/9 : FROM ruby:2.4.1-alpine
 ---> 5eadd5d1419a
Step 2/9 : LABEL maintainer "https://github.com/tootsuite/mastodon" description "A GNU Social-compatible microblogging server"
 ---> Using cache
 ---> fceff421dcd0
Step 3/9 : ENV RAILS_ENV production NODE_ENV production
 ---> Using cache
 ---> 670c840adc5b
Step 4/9 : EXPOSE 3000 4000
 ---> Using cache
 ---> 5a06484cfb13
Step 5/9 : WORKDIR /mastodon
 ---> Using cache
 ---> f6bf9c37cd0c
Step 6/9 : COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
 ---> Using cache
 ---> 304510b4ed8a
Step 7/9 : RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*
 ---> Using cache
 ---> 1149feaeec73
Step 8/9 : COPY . /mastodon
 ---> Using cache
 ---> 62ea0c5fe1af
Step 9/9 : VOLUME /mastodon/public/system /mastodon/public/assets
 ---> Using cache
 ---> 6e02c6dd9be8
Successfully built 6e02c6dd9be8
Building sidekiq
Step 1/9 : FROM ruby:2.4.1-alpine
 ---> 5eadd5d1419a
Step 2/9 : LABEL maintainer "https://github.com/tootsuite/mastodon" description "A GNU Social-compatible microblogging server"
 ---> Using cache
 ---> fceff421dcd0
Step 3/9 : ENV RAILS_ENV production NODE_ENV production
 ---> Using cache
 ---> 670c840adc5b
Step 4/9 : EXPOSE 3000 4000
 ---> Using cache
 ---> 5a06484cfb13
Step 5/9 : WORKDIR /mastodon
 ---> Using cache
 ---> f6bf9c37cd0c
Step 6/9 : COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
 ---> Using cache
 ---> 304510b4ed8a
Step 7/9 : RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*
 ---> Using cache
 ---> 1149feaeec73
Step 8/9 : COPY . /mastodon
 ---> Using cache
 ---> 62ea0c5fe1af
Step 9/9 : VOLUME /mastodon/public/system /mastodon/public/assets
 ---> Using cache
 ---> 6e02c6dd9be8
Successfully built 6e02c6dd9be8
Building streaming
Step 1/9 : FROM ruby:2.4.1-alpine
 ---> 5eadd5d1419a
Step 2/9 : LABEL maintainer "https://github.com/tootsuite/mastodon" description "A GNU Social-compatible microblogging server"
 ---> Using cache
 ---> fceff421dcd0
Step 3/9 : ENV RAILS_ENV production NODE_ENV production
 ---> Using cache
 ---> 670c840adc5b
Step 4/9 : EXPOSE 3000 4000
 ---> Using cache
 ---> 5a06484cfb13
Step 5/9 : WORKDIR /mastodon
 ---> Using cache
 ---> f6bf9c37cd0c
Step 6/9 : COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
 ---> Using cache
 ---> 304510b4ed8a
Step 7/9 : RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories  && BUILD_DEPS="     postgresql-dev     libxml2-dev     libxslt-dev     python     build-base"  && apk -U upgrade && apk add     $BUILD_DEPS     nodejs@edge     nodejs-npm@edge     libpq     libxml2     libxslt     ffmpeg     file     imagemagick@edge  && npm install -g npm@3 && npm install -g yarn  && bundle install --deployment --without test development  && yarn --ignore-optional  && yarn cache clean  && npm -g cache clean  && apk del $BUILD_DEPS  && rm -rf /tmp/* /var/cache/apk/*
 ---> Using cache
 ---> 1149feaeec73
Step 8/9 : COPY . /mastodon
 ---> Using cache
 ---> 62ea0c5fe1af
Step 9/9 : VOLUME /mastodon/public/system /mastodon/public/assets
 ---> Using cache
 ---> 6e02c6dd9be8
Successfully built 6e02c6dd9be8

あっさり終了しました。イマイチなにをやっているのかわからないんですけどねw

postgres のユーザーと db の設定

docker コンテナとして作成された postgres の初期設定ですね。これはいつもやっているような作業なので非常にわかりやすくて良いですw

# docker exec -it mastodon_db_1 /bin/bash
bash-4.3#

docker コンテナの中の bash を起動します。この辺の作業はネットワーク関連でハマった時に、散々コンテナの中から ping を撃つとかやったので、だいぶ慣れてきました。

bash-4.3# su - postgres
$ echo $SHELL
/bin/sh
$ pwd
/var/lib/postgresql

なんだかえらく特殊な環境な気がします。こういう手順なんだ、と思って作業を進めます。

$ createuser -P <ヒミツUser>
Enter password for new role: <ヒミツPass>
Enter it again: <ヒミツPass>
$ createdb <ヒミツDb> -O <ヒミツUser>

このへんは .env.production に記載した DB_USER DB_NAME DB_PASS を設定します。

試しに……

$psql -d db -U user
psql (9.6.2)
Type "help" for help.

db=> \pset pager off
Pager usage is off.
db=> \l
                                  List of databases
    Name     |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-------------+----------+----------+------------+------------+-----------------------
 postgres    | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 db          | user     | UTF8     | en_US.utf8 | en_US.utf8 |
 template0   | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
             |          |          |            |            | postgres=CTc/postgres
 template1   | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
             |          |          |            |            | postgres=CTc/postgres
(4 rows)

db=> \q
could not save history to file "/var/lib/postgresql/.psql_history": Permission denied

まぁ中に入っちゃえば普通の postgres ですね……当たり前か。最後に出た Permission denied は気にしなくて良いですね。そもそもこの postgres ユーザーが psql なんかでローカルから接続することは想定してないでしょうし。

$ exit
bash-4.3# exit
exit
#

さて遊んでないで exit します。

db のマイグレーション

1つ前の作業では空っぽの db を作っただけなので、ここで中身のテーブルやらを作るんですね。

# docker-compose run --rm web rails db:migrate
Migrating to CreateAccounts (20160220174730)
== 20160220174730 CreateAccounts: migrating ===================================
-- create_table(:accounts, {})
   -> 0.0971s
-- add_index(:accounts, [:username, :domain], {:unique=>true})
   -> 0.0332s
== 20160220174730 CreateAccounts: migrated (0.1306s) ==========================
 :
~略~
 :
Migrating to AddIndexesToReportsForAccounts (20170418160728)
== 20170418160728 AddIndexesToReportsForAccounts: migrating ===================
-- add_index(:reports, :account_id)
   -> 0.0360s
-- add_index(:reports, :target_account_id)
   -> 0.0343s
== 20170418160728 AddIndexesToReportsForAccounts: migrated (0.0705s) ==========
# 

だーっと流れて、ちらちら ddl っぽいものが見えて終了しました。

アセットの事前コンパイル

よくわかっていませんが、rails で管理される script やら css やら画像やらですね。リアルタイムでも処理できるけど、事前にできる変換とかは事前に片付けて処理を軽く速くしましょう……という作業だと思います。

# docker-compose run --rm web rails assets:precompile
 :
 :
I, [2017-04-25T06:38:18.699166 #1]  INFO -- : Writing /mastodon/public/assets/pghero/application-a013dbdf269bc5d5f3610778edb4075c172f162ee90827f8839c4e8128a3a54d.js.gz
I, [2017-04-25T06:38:20.461783 #1]  INFO -- : Writing /mastodon/public/assets/pghero/application-9bc22f0902dcd973784cb5dd4a5fd5f7437691f893fe23bef94cfb6ae256059b.css
I, [2017-04-25T06:38:20.461968 #1]  INFO -- : Writing /mastodon/public/assets/pghero/application-9bc22f0902dcd973784cb5dd4a5fd5f7437691f893fe23bef94cfb6ae256059b.css.gz
#

どばっと、png やら svg やら js やらの何かのログが流れて完了しました。

docker コンテナの再起動

docker-compose stop コマンドを投げます。

# docker-compose stop
Stopping mastodon_db_1 ... done
Stopping mastodon_redis_1 ... done

開始する時は docker-compose up -d を使うようです。

# docker-compose up -d
Starting mastodon_redis_1
Starting mastodon_db_1
Starting mastodon_web_1
Starting mastodon_sidekiq_1
Starting mastodon_streaming_1

おぉぉなんか上がってきた。

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                              NAMES
f104cef00b19        gargron/mastodon    "bundle exec rails..."   3 minutes ago       Up 2 minutes        0.0.0.0:3000->3000/tcp, 4000/tcp   mastodon_web_1
bc408422a8cf        gargron/mastodon    "npm run start"          3 minutes ago       Up 2 minutes        3000/tcp, 0.0.0.0:4000->4000/tcp   mastodon_streaming_1
a830929f13af        gargron/mastodon    "bundle exec sidek..."   3 minutes ago       Up 2 minutes        3000/tcp, 4000/tcp                 mastodon_sidekiq_1
9726ee71b239        postgres:alpine     "docker-entrypoint..."   About an hour ago   Up 2 minutes        5432/tcp                           mastodon_db_1
c1cb95481e8c        redis:alpine        "docker-entrypoint..."   About an hour ago   Up 2 minutes        6379/tcp                           mastodon_redis_1

いっぱいいますね。記事にあるとおりに稼働確認してみます。

# curl localhost:3000
<html><body>You are being <a href="http://localhost:3000/about">redirected</a>.</body></html>

おぉぉ返ってきた。ということはブラウザで http://ip.addr.for.svr:3000 すれば…… これも、.env.production で LOCAL_HTTPSfalse にしていないとできません。

おぉぉぉぉぉぉぉぉ! おぉぉぉぉ は nginx なりの reverse proxy の設定ができるまでオアズケです……ただ、逆に言えば LOCAL_HTTPSfalse にしておけば、外に公開する前にダイレクトに接続して色々と運用準備ができるということですね。いざ外に出す時には .env.production を修正して……

# docker-compose stop
# docker-compose rebuild
# docker-compose up -d

……とかやれば切り替えできそうです。できそうです、と言うか、そうしましたw

nginx で reverse proxy

あとは reverse proxy の ssl 設定とか転送設定ですね。この記事では割愛しますが公式ドキュメントに掲載されている nginx の conf を本当にそのまま忠実に使用する1)のが良いと思います。以下の設定だけは proxy_pass を追記しています。

       location /assets {
               proxy_pass http://ip.addr.for.backend:3000/assets;
               add_header Cache-Control "public, max-age=31536000, immutable";
       }

これ、そのままだとヘッダー追加するだけで proxy せずに nginx に設定されているドキュメントルートを見に行きますよね。うちの環境は、フロントの reverse proxy が別サーバーで立っているので、これだと動かないんですよね。

let's encrypt 関連はこの wiki でもサーバー証明書 とかに書いてあります。

mastodon の管理者になる

構築が終わったので自分のアカウントを mastodon の管理者にしておきます。

まずは自分のアカウントを作る

とりあえず mastodon のトップ画面でユーザー名、メールアドレス、パスワードを入れて[参加する]します。

そうすると、構築時に指定したメールサーバーを通じて、アカウントのメールアドレスに認証用の url がメールで飛んできます。この url は .env.production の LOCAL_DOMAIN の設定あたりが効いているようですね。

うまくいきましたw それでは改めて登録したメールアドレスとパスワードでログインします。

おっけーです。この画面まで来たら、1回サーバーに戻って自分を管理者にします。

自分のアカウントを管理者登録する

mastodon_web_1 環境の shell に入ります。

# docker exec -it mastodon_web_1 /bin/sh

以下のコマンドで管理者登録するようです。

/mastodon # RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME=
YoTTaBoozer
Congrats! YoTTaBoozer is now an admin. \o/
Navigate to http://mastodon.manimani.cc/admin/settings to get started

登録できたら mastodon_web_1 環境を抜けます。

/mastodon # exit

もうひとつやっておく

まずもって Mastodon 自体のこともまだよくわかっていないのでなんともですが、Mastodonのサーバ間通信が切れた場合のリカバリ こちらの記事にあるとおり mastodon:daily を回すようにしようと思います。

うちは systemd 環境なので、こんな service ファイルを /etc/systemd/system/mastodon.service として作成しました。

[Unit]
Description=Mastodon daily

[Service]
Type=oneshot
ExecStart=/bin/bash -l -c 'cd /srv/docker/mastodon && docker-compose run --rm web rake mastodon:daily'

そして同じ場所に /etc/systemd/system/mastodon.timer ファイルを作ります。

[Unit]
Description=Mastodon daily schedule

[Timer]
OnCalendar=*-*-* 04,16:00:00
Unit=mastodon.service

[Install]
WantedBy=timers.target

こんな感じかな。

とりあえず運用してみよう

とりあえずは、試験運用ですね。実際問題ストレージどうするかとか、バックアップどうするかとかはこれから考えてみないと。ヤバいと思ったらいつでもサーバーごと叩き落とす心構えで運用してみましょうか。

1)
もちろん url とか proxy_pass とかは環境にあわせますが……