Bhyveを利用してDockerを動かす

投稿者: | 2026年5月12日

FreeBSDでDockerを動かす場合、いくつかの選択肢がありますが、一番簡単で安定しているBhyveベースでDocker環境を構築します。

前提

  • NetBoxでインベントリー管理
  • Bhyve管理にvm-bhyve利用
  • Docker実行用に軽量なAlpineLinux virt v3.23.4を利用
  • AlpineLinuxはあえてgrubブート

AlpineLinux仮想環境構築

roles/freebsd/tasks/vm_bhyve_alpinelinux.yaml

- name: Set AlpineLinux variables
  set_fact:
    alpinelinux_org: "https://dl-cdn.alpinelinux.org/alpine"
    alpinelinux_ver: "3.23"
    alpinelinux_ver_rev: "4"
    alpinelinux_flavor: "virt"
    alpinelinux_kernel: "virt"
    alpinelinux_arch: "x86_64"
    alpinelinux_host: "docker"

- name: Set ISO
  set_fact:
    iso: "alpine-{{ alpinelinux_flavor }}-{{ alpinelinux_ver }}.{{ alpinelinux_ver_rev }}-{{ alpinelinux_arch }}.iso"

- name: Check if {{ iso }} exists
  stat:
    path: "/vm/.iso/{{ iso }}"
  register: iso_file

- name: Get AlpineLinux ISO
  command: |
    vm iso {{ alpinelinux_org }}/v{{ alpinelinux_ver }}/releases/{{ alpinelinux_arch }}/{{ iso }}
  register: result
  when:
    - not iso_file.stat.exists
    - vm_bhyve_installed
  changed_when: false

- name: Check if {{ alpinelinux_host }}.conf exists
  stat:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
  register: conf_file

- name: Check if template file exists
  stat:
    path: /vm/.templates/alpine.conf
  register: alpine_conf_file

- name: Check if template file exists
  stat:
    path: /vm/.templates/legacy-alpine.conf
  register: legacy_alpine_conf_file

- name: Create {{ alpinelinux_host }}
  command: |
    vm create -t alpine -c 2 -m 2G -s 20G {{ alpinelinux_host }}
  register: result
  when:
    - alpine_conf_file.stat.exists
    - not conf_file.stat.exists
    - vm_bhyve_installed
  changed_when: false

- name: Create {{ alpinelinux_host }}
  command: |
    vm create -t legacy-alpine -c 2 -m 2G -s 20G {{ alpinelinux_host }}
  register: result
  when:
    - legacy_alpine_conf_file.stat.exists
    - not conf_file.stat.exists
    - vm_bhyve_installed
  changed_when: false

- name: Fix grub_install0
  lineinfile:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
    regexp: '^grub_install0="linux /boot/vmlinuz-vanilla initrd=/boot/initramfs-vanilla alpine_dev=cdrom:iso9660 modules
=loop,squashfs,sd-mod,usb-storage,sr-mod"$'
    line: 'grub_install0="linux /boot/vmlinuz-{{ alpinelinux_kernel }} initrd=/boot/initramfs-{{ alpinelinux_kernel }} a
lpine_dev=cdrom:iso9660 modules=loop,squashfs,sd-mod,usb-storage,sr-mod"'
  when:
    - vm_bhyve_installed

- name: Fix grub_install1
  lineinfile:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
    regexp: '^grub_install1="initrd /boot/initramfs-vanilla"$'
    line: 'grub_install1="initrd /boot/initramfs-{{ alpinelinux_kernel }}"'
  when:
    - vm_bhyve_installed

- name: Fix grub_run0
  lineinfile:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
    regexp: '^grub_run0="linux /boot/vmlinuz-vanilla root=/dev/vda3 modules=ext4"$'
    line: 'grub_run0="linux /boot/vmlinuz-{{ alpinelinux_kernel }} root=/dev/vda3 modules=ext4"'
  when:
    - vm_bhyve_installed

- name: Fix grub_run1
  lineinfile:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
    regexp: '^grub_run1="initrd /boot/initramfs-vanilla"$'
    line: 'grub_run1="initrd /boot/initramfs-{{ alpinelinux_kernel }}"'
  when:
    - vm_bhyve_installed

- name: Update {{ alpinelinux_host }} configuration
  blockinfile:
    path: "/vm/{{ alpinelinux_host }}/{{ alpinelinux_host }}.conf"
    block: |
      disk1_type="ahci-cd"
      disk1_dev="custom"
      disk1_name="/vm/.iso/{{ iso }}"
  when:
    - vm_bhyve_installed

- name: Check if {{ iso }} exists
  stat:
    path: "/vm/.iso/{{ iso }}"
  register: iso_file

- name: Install {{ alpinelinux_host }}
  command: |
    vm install {{ alpinelinux_host }} {{ iso }}
  register: result
  when:
    - iso_file.stat.exists
    - vm_bhyve_installed
  changed_when: false

- name: vm_list
  community.general.sysrc:
    name: vm_list
    value: "{{ alpinelinux_host }}"
  when:
    - vm_bhyve_installed

インストール

コンソールログイン

vm console docker
login: root

インストールスクリプト作成

Bhyveのgrubがext4のブート領域からカーネルをブートできないので、setup-alpine実行後にext2でブート領域を再作成します。

/setup.sh

#!/bin/sh
setup-alpine
mount /dev/vda3 /mnt
mount /dev/vda1 /mnt/boot
mkdir -p /tmp/boot
cp -pr /mnt/boot/* /tmp/boot/
umount /mnt/boot
mkfs.ext2 -O ^64bit /dev/vda1
mount -t ext2 /dev/vda1 /mnt/boot
cp -pr /tmp/boot/* /mnt/boot/
umount /mnt/boot
NEW_UUID=`blkid -s UUID -o value /dev/vda1`
cp -p /mnt/etc/fstab /mnt/etc/fstab.orig
sed -i "/\/boot/c\UUID=${NEW_UUID}\t\/boot\text2\trw,relatime\t0 2" /mnt/etc/fstab
umount /mnt
reboot

実行

/setup.sh

Docker

Ansibleの有効化

ssh -l root docker
login: root
password: XXXXXXXXXXXXXXXXXXX
apk add python3
apk add sshpass
mkdir -p /root/.ssh
chmod 700 /root/.ssh
cat > /root/.ssh/authorized_keys
鍵をペースト
^D

Dockerの有効化

roles/alpinelinux/tasks/docker.yaml

- name: Update repo
  lineinfile:
    path: /etc/apk/repositories
    regexp: '^#http://dl-cdn.alpinelinux.org/alpine/v{{ alpinelinux_ver }}/community$'
    line: http://dl-cdn.alpinelinux.org/alpine/v{{ alpinelinux_ver }}/community

- name: Update repo
  blockinfile:
    path: /etc/apk/repositories
    block: |
      http://dl-cdn.alpinelinux.org/alpine/edge/main
      http://dl-cdn.alpinelinux.org/alpine/edge/community
      http://dl-cdn.alpinelinux.org/alpine/edge/testing

- name: Ensure /etc/docker directory installed
  file:
    path: /etc/docker
    state: directory
    mode: "0755"

- name: /etc/docker/daemon.json
  copy:
    dest: /etc/docker/daemon.json
    content: |
      {
          "firewall-backend": "nftables"
      }

- name: apk add
  command: apk add docker docker-compose
  register: result

- name: Add net.ipv4.ip_forward=1
  lineinfile:
    path: /etc/sysctl.conf
    regexp: '^net.ipv4.ip_forward='
    line: net.ipv4.ip_forward=1

- name: Reload sysctl
  command: sysctl -p

- name: Start docker
  service:
    name: docker
    state: started

- name: update docker
  command: rc-update add docker boot

ローカル docker run 実行テスト

docker run --rm hello-world

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

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

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

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

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

リモート docker 実行スクリプト

docker.sh

#!/bin/sh

DOCKER_HOST="docker"
DOCKER_ARGS="$*"

ssh -l root $DOCKER_HOST "docker $DOCKER_ARGS"

参考

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です