C# でもビットスワップしたい
対象
以下のマニアックな人向けの記事です。
- C#
- LSB と MSB を入れ替えたい
ファーム焼きをしている界隈の人に刺さるかもしれません。 むしろモトローラコードのエンディアンを変換するプログラムを提供しなさいとも言われるかもしれませんが。
方法
ビット演算で入れ替える
using System; namespace BitReverse { /// <summary> /// Swap MSB and LSB /// </summary> public static class BitReverse { /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static ulong UInt64(ulong input) { return ReverseBit(input, 64); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static uint UInt32(uint input) { return (uint)ReverseBit(input, 32); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static ushort UInt16(ushort input) { return (ushort)ReverseBit(input, 16); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static byte UInt8(byte input) { return (byte)ReverseBit(input, 8); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <param name="bit">size of bits</param> /// <returns>Swapped input number</returns> /// <remarks> /// Original code is from https://ja.stackoverflow.com/a/9239/882 /// </remarks> private static ulong ReverseBit(ulong input, int bit) { ulong swap = input; switch (bit) { case 64: swap = ((swap & 0x00000000ffffffff) << 32) | ((swap >> 32) & 0x00000000ffffffff); goto case 32; case 32: swap = ((swap & 0x0000ffff0000ffff) << 16) | ((swap >> 16) & 0x0000ffff0000ffff); goto case 16; case 16: swap = ((swap & 0x00ff00ff00ff00ff) << 8) | ((swap >> 8) & 0x00ff00ff00ff00ff); goto case 8; case 8: swap = ((swap & 0x0f0f0f0f0f0f0f0f) << 4) | ((swap >> 4) & 0x0f0f0f0f0f0f0f0f); goto case 4; case 4: swap = ((swap & 0x3333333333333333) << 2) | ((swap >> 2) & 0x3333333333333333); goto case 2; case 2: swap = ((swap & 0x5555555555555555) << 1) | ((swap >> 1) & 0x5555555555555555); break; default: throw new ArgumentException("bit is out of range: 2/4/8/16/32/64", nameof(bit)); } return swap; } } }
C# だと fail through が出来ないので、 goto を使っています。安全ですね。
参考文献
ループしてビットを入れ替える
using System; namespace BitReverse { /// <summary> /// Swap MSB and LSB /// </summary> public static class BitReverseLoop { /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static ulong UInt64(ulong input) { return ReverseBit(input, 64); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static uint UInt32(uint input) { return (uint)ReverseBit(input, 32); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static ushort UInt16(ushort input) { return (ushort)ReverseBit(input, 16); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <returns>Swapped input number</returns> public static byte UInt8(byte input) { return (byte)ReverseBit(input, 8); } /// <summary> /// Swap MSB and LSB /// </summary> /// <param name="input">input number</param> /// <param name="bit">size of bits</param> /// <returns>Swapped input number</returns> /// <remarks> /// Original code is from https://ja.stackoverflow.com/a/7500/882 /// </remarks> private static ulong ReverseBit(ulong input, int bit) { ulong swap = 0; while(bit-- > 0) { swap <<= 1; swap |= (input & 1u); input >>= 1; } return swap; } } }
1Lu とかにしないといけないように見えるけど、暗黙的型変換されるので 1u で良いです。
参考文献
ライセンス
stackoverflow のライセンスに基づきます。CC BY-SA 3.0。 私が記載したものは WTFPL Version 2.0 とします。
その他
テストコード等は gist を参照ください。
ZFS で RAID-Z EXPANSION を試してみる
ZFS RAID-Z ではディスクの追加が出来ないというのは過去の話(since 2025.01)。
対象
準備 (ZFS を更新した場合)
zpool status で警告が出ている場合はアップグレードする。
既に、対応済みのバージョンになっていればOK。 RAID-Z の拡張を行うには raidz_expansion が必要。
$ sudo zpool upgrade tank This system supports ZFS pool feature flags. Enabled the following features on 'tank': zilsaxattr head_errlog blake3 block_cloning vdev_zaps_v2 redaction_list_spill raidz_expansion fast_dedup longname large_microzap
手順
tank に raidz2-0 が構築されている前提で説明。
$ sudo zpool status pool: tank state: ONLINE scan: scrub repaired 0B in 1 days 09:29:20 with 0 errors on Mon Aug 11 09:53:22 2025 config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 raidz2-0 ONLINE 0 0 0 sda ONLINE 0 0 0 sdb ONLINE 0 0 0 sdc ONLINE 0 0 0 sdd ONLINE 0 0 0
tank に sde を追加する場合は以下のコマンドを実行する。 ※ 説明のため sde としていますが、実際の運用では disk id の方が良いです
$ sudo zpool attach tank raidz2-0 /dev/sde # usage: # zpool attach [-fsw] [-o property=value] <pool> <device> <new-device>
参考: https://docs.oracle.com/cd/E19253-01/819-6260/gcfhe/index.html openzfs.github.io
expansion が以下のように進行します。4T で 2日ほどかかる模様。
$ sudo zpool status pool: tank state: ONLINE scan: scrub repaired 0B in 1 days 09:29:20 with 0 errors on Mon Aug 11 09:53:22 2025 expand: expansion of raidz2-0 in progress since Mon Sep 1 01:43:15 2025 3.96G / 13.9T copied at 63.3M/s, 0.03% done, 2 days 16:04:05 to go config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 raidz2-0 ONLINE 0 0 0 sda ONLINE 0 0 0 sdb ONLINE 0 0 0 sdc ONLINE 0 0 0 sdd ONLINE 0 0 0 sde ONLINE 0 0 0
expansion が完了すると自動的に scrub が走り、 scrub 後に容量が増える。
バックグラウンドで raidz_expand というプロセスが動いて、ブロックの再配置を指示してくれている模様。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1566 root 20 0 0 0 0 D 6.6 0.0 0:45.86 raidz_expand
HDD への操作なので、 iowait が凄いのは言うまでもない。
しくみメモ
既存 RAID と RAID-Z の違い
| RAID 4/5/6 | RAID-Z | |
|---|---|---|
| パリティ計算 | する | しない |
| ストライプ幅 | 変わる | 変わらない |
| 再配置 | 全データ | リフロー |
| オンライン拡張 | OCE対応なら可能 | 可能 |
| 拡張領域の利用 | 追加直後 | リフロー完了後 |
| 中断 | 不可能 | 可能 |
| ストライプレベルの変更 | 可能 | 不可能 |
再構築の事をリフローと呼んでいるみたいで、拡張した後の読み込み操作で再配置を行っているとのこと。 そのため、 scrub を実行することで容量が増える模様。 リフロー中に同一ブロックが同じHDDに割り当てられないようにケアするのが大変だったとのこと。同一ブロックが同じHDDに割り当てられてしまって、該当HDDが破損した場合にデータを保証できなくなるのを回避するのが大変だったとのこと(?)。
資料
こちらは最初のデザイン? RAID-Z Expansion
OpenZFS Developper Summit 2023 でこの機能がお披露目された模様。 openzfs.org RAID-Z Expansion.pdf www.youtube.com
debian 13 で zfsonlinux
HDDがお亡くなりになって気が付いたら debian 13 がインストールされたので、メモです。
対象
準備
debian 13 の場合
contrib を追加して、インストールすればOK。 最新を使いたい場合は trixie-backports を利用ください(下記参照)。
grep "trixie main" /etc/apt/sources.list \ | sed -E "s/main .+$/contrib/" \ > sudo tee /etc/apt/sources.list.d/trixie-contrib.list
結果:
$ cat /etc/apt/sources.list.d/trixie-contrib.list
deb http://ftp.nara.wide.ad.jp/debian/ trixie contrib
deb-src http://ftp.nara.wide.ad.jp/debian/ trixie contrib
参考: バージョンは 2.3.2系が入る Debian -- Details of package zfs-dkms in trixie
debian 13 で zfs の最新を使いたい場合
backports リポジトリを追加して、インストールすればOK。
grep "trixie main" /etc/apt/sources.list \ | sed -E "s/bookworm.+$/trixie-backports main contrib/" \ > sudo tee /etc/apt/sources.list.d/trixie-backports.list
結果:
$ cat /etc/apt/sources.list.d/trixie-backports.list
deb http://deb.debian.org/debian trixie-backports main contrib
deb-src http://deb.debian.org/debian trixie-backports main contrib
cat <<EOF | sudo tee /etc/apt/preferences.d/90_zfs Package: src:zfs-linux Pin: release n=trixie-backports Pin-Priority: 990 EOF
参考: バージョンは 2.3.3系が入る Debian -- Details of package zfs-dkms in trixie-backports
debian 12 の場合
debian 12 の場合は、backports リポジトリを追加して、インストールすればOK。 debian 13 (trixie) にこの手順をそのまま適用すると依存関係で盛大にエラーとなります。
grep "bookworm main" /etc/apt/sources.list \ | sed -E "s/bookworm.+$/bookworm-backports main contrib/" \ > sudo tee /etc/apt/sources.list.d/bookworm-backports.list
結果:
$ cat /etc/apt/sources.list.d/bookworm-backports.list
deb http://deb.debian.org/debian bookworm-backports main contrib
deb-src http://deb.debian.org/debian bookworm-backports main contrib
cat <<EOF | sudo tee /etc/apt/preferences.d/90_zfs Package: src:zfs-linux Pin: release n=bookworm-backports Pin-Priority: 990 EOF
参考: バージョンは 2.3.2系が入る Debian -- Details of package zfs-dkms in bookworm-backports
パッケージをインストール(共通)
apt update apt install dpkg-dev linux-headers-generic linux-image-generic apt install zfs-dkms zfsutils-linux # VMなど標準入力が使えない場合: # DEBIAN_FRONTEND=noninteractive apt install zfs-dkms zfsutils-linux
補足
2.3系で RAIDZ Expansion が出来るようになった(RAID-Z でディスク追加が出来るようになった)ので、やばいです。
参考文献
libvirt で GPU の仮想化を有効にしてみる
やりたいこと
libvirt で仮想マシンを立てているが、GPU を使いたい
対象
- debian 12
- CPU: intel 第5世代~第10世代
- libvirt で qemu 環境を構築したい
- 複数の VM で GPU を切り替えたい
- VM が secure boot に対応していること
- 注意: libvirt 上から スナップショットを取れなくなります
- virtual machine - Is there a way to share a GPU with a guest VM in the same way we can share a CPU using VT-x/AMD-V? - Super User
- 既存の VM が BIOS 起動の場合は、 gpt ディスクへ変換して XML を触らないと起動しなくなります(高度)
- ↑再インストールの方が楽です
- kernel が古いと gvt が
guest page write errorとなる可能性がある- https://www.reddit.com/r/VFIO/comments/148mzp5/windows_10_vm_running_blueiris_has_igfx_driver/
I had problems with kernel versions from 5.12 to 6.2, VMs would always crashとのことなので、最新の kernelを使いましょう(未検証)
- この現象が発生すると qemu が defenct になって kill できない(親が init なのでもっと kill できない)
- https://www.reddit.com/r/VFIO/comments/148mzp5/windows_10_vm_running_blueiris_has_igfx_driver/
インストール
0. KVM の インストールと設定
既にKVM環境を構築済みの場合はこの手順は不要です。
sudo apt install libvirt-daemon-system qemu-system
リモートからSSHで接続して virt-manager を設定できるようにする。
$ sudo vi /etc/libvirt/libvirtd.conf # Listen for unencrypted TCP connections on the public TCP/IP port. # ... # This is disabled by default, uncomment this to enable it. listen_tcp = 1 # Override the port for accepting insecure TCP connections # This can be a port number, or service name # # This setting is not required or honoured if using systemd socket # activation. # tcp_port = "16509"
あとは libvirt をリロードするだけ。
$ sudo systemctl reload libvirtd
Windows マシンで、 WSL2 が入っていたら、 virt-manager を使えるので、GUIで簡単に制御できる。
# WSL上で実行してください(debian系) apt install virt-manager # SSHキーを転送 ssh-keygen -t rsa -b 4096 ssh-copy-id example-username@example-hostname # ログインできることを確認 ssh example-username@example-hostname # virt-manager で接続する virt-manager -c example-username@example-hostname
virt-manager でGUIへ接続する場合は、 Display を VNC server と設定しないと、接続できません。(TLSを設定すればできるのですが、そこまでやっていません)
LINUX Kernel の設定
1. 環境確認
QEMUのバージョン確認(2.12以上)
$ qemu-system-x86_64 --version QEMU emulator version 7.2.4 (Debian 1:7.2+dfsg-7+deb12u1) Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers $ apt info qemu-system Package: qemu-system Version: 1:7.2+dfsg-7+deb12u1 Priority: optional Section: otherosfs Source: qemu ....
qemu が 2.12以上ならOK(最近のlinux ならほぼクリアしている)。
CPUの状態確認。
$ cat /proc/cpuinfo | grep model model : 94 model name : Intel(R) Core(TM) i3-6100 CPU @ 3.70GHz
Intel 系でかつ、第5世代~第10世代であること。
2. kernel パラメータの調整 (IOMMU を有効化)
i915.enable_gvt=1 intel_iommu=on をパラメータに与える。
$ sudo vi /etc/default/grub # GRUB_CMDLINE_LINUX="" GRUB_CMDLINE_LINUX="i915.enable_gvt=1 i915.enable_guc=0 intel_iommu=on"
CPU が第10世代~第11世代の場合は次の資料で設定を確認して、必要に応じてオプションを追加すること。 wiki.archlinux.org
参考: オプションの種類を確認する方法
$ sudo modinfo i915 | grep -P "enable_gvt|enable_guc" parm: enable_guc:Enable GuC load for GuC submission and/or HuC load. Required functionality can be selected using bitmask values. (-1=auto [default], 0=disable, 1=GuC submission, 2=HuC load) (int) parm: enable_gvt:Enable support for Intel GVT-g graphics virtualization host support(default:false) (bool)
3. kernel モジュールのロード設定
kvmgt, vfio-iommu-type1, mdev を有効にする。
$ sudo vi /etc/modules-load.d/kvmgt.conf
# Load kvmgt, vfio-iommu-type1 and mdev
kvmgt
gvt を使っている時に出てくるエラーを無視する設定を行う。
$sudo vi /etc/modprobe.d/kvm.conf options kvm ignore_msrs=Y report_ignored_msrs=N
4. grub へ反映
grub の設定を行う。
※事前に /boot/grub/grub.cfg のバックアップを取得したほうが良いかも
$ sudo update-grub Generating grub configuration file ... Found linux image: /boot/vmlinuz-6.1.0-12-amd64 Found initrd image: /boot/initrd.img-6.1.0-12-amd64 Found linux image: /boot/vmlinuz-6.1.0-10-amd64 Found initrd image: /boot/initrd.img-6.1.0-10-amd64 Warning: os-prober will not be executed to detect other bootable partitions. Systems on them will not be added to the GRUB boot configuration. Check GRUB_DISABLE_OS_PROBER documentation entry. done
5. 再起動
再起動して、grub を反映する。
KVM の設定
6. KVM の hook 設定
必要なツールをインストール
# libxml2-utils は xmllint のため、 uuid-runtime は uuidgen コマンドを使うため
$ apt install libxml2-utils uuid-runtime
libvirtd 用の hook を設定する。
$ sudo vi /etc/libvirt/hooks/qemu
#!/bin/sh
GVT_PCI="0000:00:02.0"
MDEV_TYPE=i915-GVTg_V5_4
GVT_GUID=`cat "/etc/libvirt/qemu/$1.xml" | xmllint --xpath 'string(/domain/devices/hostdev[@type="mdev"][@mode="subsystem"][@display][@model="vfio-pci"]/source/address/@uuid)' -`
# echo "$1 $2 $3 $GVT_GUID" >> /tmp/libvirt_gvthook
if [ $# -ge 3 ] && [ -n "$GVT_GUID" ]; then
# echo gvt_ok >> /tmp/libvirt_gvthook
if [ "$2" = "prepare" ] && [ "$3" = "begin" ]; then
echo "$GVT_GUID" > "/sys/bus/pci/devices/$GVT_PCI/mdev_supported_types/$MDEV_TYPE/create"
elif [ "$2" = "release" ] && [ "$3" = "end" ]; then
echo 1 > "/sys/bus/pci/devices/$GVT_PCI/devices/$GVT_GUID/remove"
fi
fi
参考: 上記コードは以下を参考に作成しました。 wiki.archlinux.org
スティッキービットを設定して、root / root で実行されるようにする
# 念のため権限を設定 $ sudo chown root:root /etc/libvirt/hooks/qemu # ユーザー・グループの権限で実行されるように設定 $ sudo chmod ug+s /etc/libvirt/hooks/qemu # その他ユーザーに実行権限を付与 $ sudo chmod o+x /etc/libvirt/hooks/qemu # 不用意に書き込み権を与えない $ sudo chmod go-w /etc/libvirt/hooks/qemu # 権限チェック $ ls -l /etc/libvirt/hooks/qemu -rwSr-Sr-x 1 root root 754 Sep 23 18:03 /etc/libvirt/hooks/qemu
VM の設定と起動
7. UEFI 起動を可能にする
ファームを適用する。
$ sudo apt install ovmf # 設定を更新 $ sudo systemctl reload libvirtd
8. 対象の VM を設定する
次の設定で VM を設定する(必須)。
Archtecture: x86_64 Chipset: Q35 Firmware: UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.ms.fd
<os> <type arch="x86_64" machine="pc-q35-7.2">hvm</type> <loader readonly="yes" type="pflash">/usr/share/OVMF/OVMF_CODE_4M.ms.fd</loader> <nvram>/var/lib/libvirt/qemu/nvram/{VMの名前}_VARS.fd</nvram> <boot dev="hd"/> </os>
注意: 起動対象の HDD(イメージ) は gpt でセキュアブートに対応していないといけません。 セキュアブートしていない場合は、GPUを一時的に認識しますが、使えない状態になります。(デバイスマネージャで警告状態となります)
9. GPU を VM に設定する
virsh で接続して、手動でXMLを追加する。
$ uuidgen
875cd399-1c1b-47f0-8d7b-9f64023c1f56
$ virsh -c qemu:///system edit win10
以下の XML に追加する。
<hostdev mode="subsystem" type="mdev" managed="no" model="vfio-pci" display="off"> <source> <address uuid="{uuidgenで生成した値をここに設定する}"/> </source> <alias name="hostdev0"/> <address type="pci" domain="0x0000" bus="0x00" slot="0x07" function="0x0"/> </hostdev>
10. 対象のVMを起動する
正常に起動したら、Intel HD Graphics がデバイスドライバから参照できます。 また、タスクマネージャにGPUの項目が出れば、成功です。
なお、GPUメモリの関係で1台しか割り当たらないことがあります。
参考文献
- GVT 関連
- Intel GVT-g - ArchWiki
- [ANNOUNCE][RFC] KVMGT - the implementation of Intel GVT-g(full GPU virtualization) for KVM gvt-g アナウンスメール
- http://www.linux-kvm.org/images/f/f3/01x08b-KVMGT-a.pdf (PDF) KVMでのGPUの仕組み(少し古い)
- https://kiyoka.moe/post/1.html - report_ignored_msrs に関する言及、参考になった
- KVM環境でIntel iGPUグラフィックを仮想マシンにパススルー(というか共有)する - naba_san’s diary こちらの方がよくまとまってるかも
lvmではないパーティションをオンライン拡張する(parted)
partedでlvmではないパーティションをオンライン拡張する
手順
1. partedでパーティションを確認する
対象のデバイス(sda)は何らかの方法で特定しておくこと。
sudo parted /dev/sda help print
実行ログ:
user@debian:~$ sudo parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) help
align-check TYPE N check partition N for TYPE(min|opt) alignment
help [COMMAND] print general help, or help on COMMAND
mklabel,mktable LABEL-TYPE create a new disklabel (partition table)
mkpart PART-TYPE [FS-TYPE] START END make a partition
name NUMBER NAME name partition NUMBER as NAME
print [devices|free|list,all|NUMBER] display the partition table, available devices, free space, all found
partitions, or a particular partition
quit exit program
rescue START END rescue a lost partition near START and END
resizepart NUMBER END resize partition NUMBER
rm NUMBER delete partition NUMBER
select DEVICE choose the device to edit
disk_set FLAG STATE change the FLAG on selected device
disk_toggle [FLAG] toggle the state of FLAG on selected device
set NUMBER FLAG STATE change the FLAG on partition NUMBER
toggle [NUMBER [FLAG]] toggle the state of FLAG on partition NUMBER
unit UNIT set the default unit to UNIT
version display the version number and copyright information of GNU Parted
(parted) print
Model: ATA SanDisk SD???????? (scsi)
Disk /dev/sda: 256GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 17.2GB 17.2GB primary linux-swap(v1)
2 17.2GB 34.4GB 17.2GB primary
3 34.4GB 172GB 137GB primary ext4
2. リサイズする
partedでディスクのサイズを拡張する。
終端サイズを指定するため、注意。あらかじめ、必要なサイズを計算すること。(実行ログでは32GBの拡張)
※「resizepart 3 204GB」では「parted: invalid token: 204GB」と言われてしまうので、次の手順とした
resize 3
yes
204GB
実行ログ:
(parted) resizepart 3 Warning: Partition /dev/sda3 is being used. Are you sure you want to continue? Yes/No? yes End? [172GB]? 204GB (parted)
3. リサイズ後の確認
print
quit
実行ログ:
(parted) print Model: ATA SanDisk SD???????? (scsi) Disk /dev/sda: 256GB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 17.2GB 17.2GB primary linux-swap(v1) 2 17.2GB 34.4GB 17.2GB primary 3 34.4GB 204GB 170GB primary ext4 (parted) quit Information: You may need to update /etc/fstab. user@debian:~$
4. ファイルシステムのリサイズ
オンラインリサイズに対応しているファイルシステムに限ります。(今回はext3/ext4)
※xfsの場合はxfs_growfs
sudo resize2fs /dev/sda3
df -h
実行ログ:
user@debian:~$ sudo resize2fs /dev/sda3 resize2fs 1.42.12 (29-Aug-2014) Filesystem at /dev/sda3 is mounted on /vmfs/hdd; on-line resizing required old_desc_blocks = 8, new_desc_blocks = 10 The filesystem on /dev/sda3 is now 41415823 (4k) blocks long. user@debian:~$ df -h Filesystem Size Used Avail Use% Mounted on /dev/dm-0 440G 14G 404G 4% / udev 10M 0 10M 0% /dev tmpfs 6.3G 708M 5.6G 12% /run tmpfs 16G 8.0K 16G 1% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 16G 0 16G 0% /sys/fs/cgroup /dev/sda3 156G 120G 29G 81% /vmfs/hdd tmpfs 3.2G 0 3.2G 0% /run/user/1000
Redmineをdockerで動かそう+サブディレクトリ
対象
- redmineを動かしたい
- host環境はできるだけ汚したくない→dockerで解決
- 関連するサービスもdocker内で動かして、完結させたい→nginxを経由させる
対象外
以下については調査・検討中の事案につき、ここでは述べない
- dockerで出力されるログの取扱い
- redmineとgitbucketの連携
- そうそうに解決しないといけない問題
- GitHub - mikoto20000/redmine_git_branch_hook: Redmine Git branch related to the issue (検証中...)
- 統合認証
- LDAP Authentication Settings · gitbucket/gitbucket Wiki · GitHub
- Samba 4.4.xでActive Directoryを1から立てる – OSAKANA TAROのメモ帳 (この辺をDockerfileにもっていけば...)
- docker pitkley/samba-ad-dc (確認中...)
- 自動起動
- バックアップ
手順
Play with Docker dockerを一時的に動かして楽しめる環境があるので、そこで実験をした。
場所は任意ディレクトリで作業を行うこと。
docker-compose.yml
注意1:パスワード等は非常に脆弱なものを使用しているので、適切に修正すること。DBのパスワードを変更する場合は、後述の事前実行コマンド内の内容も変更すること。
注意2:play-with-dockerでviを使って以下のコマンドを貼り付けるとautoindentが効いてしまうので、「:set noautoindent」としてから貼り付けると幸せになる可能性がある。
version: '3.1'
services:
redmine:
image: redmine:3.4.2-passenger
#ports:
# - "8080:3000"
environment:
REDMINE_DB_POSTGRES: db
REDMINE_DB_PASSWORD: redmine
REDMINE_DB_USERNAME: redmine
REDMINE_DB_DATABASE: redmine
RAILS_RELATIVE_URL_ROOT: /redmine
#SMTP_USER: address@hoge.com
#SMTP_PASS: password
# restart: always
depends_on:
- adminer
links:
- db
volumes:
- /usr/src/redmine/files
- ./redmine_config.ru:/usr/src/redmine/config.ru
gitbucket:
image: f99aq8ove/gitbucket
environment:
GITBUCKET_DB_URL: jdbc:postgresql://db/gitbucket
GITBUCKET_DB_USER: gitbucket
GITBUCKET_DB_PASSWORD: gitbucket
JAVA_OPTS: -Xmx1g
GITBUCKET_OPTS: --prefix=/gitbucket
depends_on:
- adminer
volumes:
- /gitbucket
ports:
- "29418:29418"
#- "8418:8080"
links:
- db
db:
image: postgres:9.6-alpine
environment:
POSTGRES_PASSWORD: example
POSTGRES_USER: work
volumes:
- /var/lib/postgresql/data
- ./postgres_create_db_users.sql:/docker-entrypoint-initdb.d/create_db_users.sql:ro
adminer:
image: adminer
ports:
- "8000:8080"
links:
- db
depends_on:
- db
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx_reverseproxy.conf:/etc/nginx/nginx.conf:ro
links:
- redmine
- gitbucket
#for debug
#command: [nginx-debug, '-g', 'daemon off;']
nginx_reverseproxy.conf
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 20; gzip on; #include /etc/nginx/conf.d/*.conf; server { #server_name localhost; listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location /gitbucket/ { proxy_pass http://gitbucket:8080/gitbucket/; } #location /adminer/ { # proxy_pass http://adminer:8080/adminer/; # #proxy_cookie_path /^/ /adminer/; #} location /redmine/ { proxy_pass http://redmine:3000/redmine/; } } } ##TCP traffic will be proxied a proxied server #server { # listen 29418; # proxy_pass gitbucket:29418; #}
事前実行スクリプト
echo "CREATE USER redmine PASSWORD 'redmine';" >> postgres_create_db_users.sql echo "CREATE DATABASE redmine;" >> postgres_create_db_users.sql echo "GRANT ALL PRIVILEGES ON DATABASE redmine TO redmine;" >> postgres_create_db_users.sql echo "CREATE USER gitbucket PASSWORD 'gitbucket';" >> postgres_create_db_users.sql echo "CREATE DATABASE gitbucket;" >> postgres_create_db_users.sql echo "GRANT ALL PRIVILEGES ON DATABASE gitbucket TO gitbucket;" >> postgres_create_db_users.sql echo "require ::File.expand_path('../config/environment', __FILE__)" > redmine_config.ru echo "map ActionController::Base.config.relative_url_root || \"/\" do" >> redmine_config.ru echo " run Rails.application" >> redmine_config.ru echo "end" >> redmine_config.ru
実行コマンド
# dockerを起動する docker-compose up -d # インスタンスをすべて削除する場合(volumeも削除しているので、注意) docker-compose stop docker-compose rm -v # 一部インスタンスに対する操作の場合(以下の例は、起動中のサービスを停止し、設定を変更して実行する) docker-compose stop nginx docker-compose rm -v nginx vi nginx_reverseproxy.conf docker-compose up -d nginx # 問題が起きた場合はログを確認する (例:nginxの場合で、起動ログに出力されているホスト名を参照する) docker-compose logs | grep nginx_1
tips
上記スクリプトを作成するにあたっての注意点など
DBへの初期データ投入
/docker-entrypoint-initdb.d 配下に*.sql、*.shを配置すると、DB初期化時に初期データを投入してくれる。
host側のsqlをコンテナ内とリンク(ro:読み取り専用)して、実行されるようにする。
docker-compose logs | grep db_1
db_1 | waiting for server to shut down....LOG: received fast shutdown request db_1 | LOG: aborting any active transactions db_1 | LOG: autovacuum launcher shutting down db_1 | LOG: shutting down db_1 | LOG: database system is shut down db_1 | done db_1 | server stopped db_1 | db_1 | PostgreSQL init process complete; ready for start up. db_1 | db_1 | LOG: database system was shut down at 2017-09-22 16:30:08 UTC db_1 | LOG: MultiXact member wraparound protections are now enabled db_1 | LOG: database system is ready to accept connections db_1 | LOG: autovacuum launcher started
上記のように、DBがいったんシャットダウンしているように見えるが、正常である。
正常であるかどうかを確認するには、「PostgreSQL init process complete; ready for start up.」が出力されていることを確認しよう。
もし、問題がある場合は、上記のログより前に、実行ログが出力されるので、その内容を確認すること。
改変履歴
- 2017/09/29
- nginxのredmineポート指定の誤りを修正
参考文献
- redmine
- gitbucket
- docker
- docker コマンド チートシート
- Docker の Data Volume まわりを整理する
- DockerのVolume機能について実験してみたことをまとめます
- Docker ComposeをDockerのswarm modeで使えるようになったので試してみた
- スタックを使ってみるのもいいかも。ログや管理について参考になる
- Docker compose ことはじめハンズオン
- 構成を作成する際に参考にした
- Docker Compose - docker-compose.yml リファレンス
- 構成を作成する際に参考にした。play-with-dockerではfrom_volumesが使えないので注意が必要。
Visual Studio Express のダウンロード
対象
以下のことをやりたい人向けの手順です。
- Visual Studio 2015 Express をダウンロードしたい
- オフラインパッケージを準備したい
Microsoftのサイト構成はコロコロ変わるので、数日したら時代遅れになっている可能性があります。
ダウンロード手順
- Visual Studio Express | Now Visual Studio Communityへアクセスする
- それでも Visual Studio Express を希望されますか?から「Express 2015 for Windows Desktop」を選択する
- そのままダウンロードページへ移動するが、ダウンロードを継続せずにURLを確認する
- 0x409→0x411へ変更し、そのURLへアクセスする
オフラインパッケージ準備手順
インストーラの言語に引きずられるので、ファイル名にJPNが入っていることを確認してから実施すること。
なお、ダウンロードしたファイルであってもオンラインへアクセスしに行く。
(防ぎたい場合はダウンロード済みのセットアップコマンドラインで「/NoRefresh /noweb」などを指定してください)
メモ
言語の変更
誤って英語版をインストールしてしまった場合は、再度インストーラを実行すれば、日本語パッケージのみのインストールが行われる。
Visual Studio 2015 言語パッケージ(日本語)が存在するが、これは、Professional等のライセンス版のみ。Expressは潔くインストーラを実行しよう。
メディアの作成
オフラインパッケージはISOファイルにならないので、手動でメディアを作成する必要があるが、全体容量が8Gを超えるため、DVD-R DL等でも入らない。
WDK10のシリーズを消して収める等考えないといけない。
