Dream Driven Development。夢を形にしよう!

LXDコンテナによる 開発環境セットアップ

LXDコンテナによる
開発環境セットアップ


コンテナ環境というとkubernetesやdockerばかりが取り上げられますが、開発環境という意味では向いていません。
LXD/LXCは「システムコンテナ」であり、docker等のような「アプリケーションコンテナ」とは異なります。

これらの特徴から考えて、アプリケーションの開発環境はLXDの方が向いています。コンテナを開発プロジェクト毎に作れば、開発環境をクリーンに保つこともできて精神的にも良いですね。

この記事では、LXDのインストール、仮想環境の立ち上げ(cloud-init)、使い方を紹介していきます。

インストール前の環境

PCは、普段から使ってるデスクトップPCです。機種の詳細は別のブログ記事を参照してください。

【自宅サーバー構築】Intel NUC PC買ったのでセットアップ:デュアルブート編 | enjoyall
【自宅サーバー構築】Intel NUC PC買ったのでセットアップ:デュアルブート編 | enjoyall
超小型PC(Intel NUC)のLinux系の開発環境構築記事です。第一回目はOSインストールです。デュアルブート環境にします!

OS: Ubuntu 20.04 LTS (Desktop)

LXDインストール

Ubuntu 20.04からLXDのインストールがsnap推奨になっているのでsnapでインストールします。
LXDのストレージで使うbtrfsはaptで入れます。(統一されてないのが気持ち悪いですね。)

~$ sudo snap install lxd
~$ sudo apt install btrfs-progs

LXDのコンフィグの初期化をします。すべてデフォルト設定で良いです。

~$ sudo lxd init

デフォルトですすめて、最後にyamlで設定を表示するところでyesと回答すると以下のような設定になっていることが確認できます。

config: {}
networks:
- config:
    ipv4.address: auto
    ipv6.address: auto
  description: ""
  name: lxdbr0
  type: ""
storage_pools:
- config:
    size: 30GB
  description: ""
  name: default
  driver: btrfs
profiles:
- config: {}
  description: ""
  devices:
    eth0:
      name: eth0
      network: lxdbr0
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default
cluster: null

LXDコンテナ作成

LXDコンテナは、たくさんあるコンテナイメージを使って作成されます。
どのようなコンテナイメージがあるかを見ていきましょう。
まずはイメージを保持してるリモートリポジトリにどんなところが登録されているのか見てみます

~$ sudo lxc remote list
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
|      NAME       |                   URL                    |   PROTOCOL    |  AUTH TYPE  | PUBLIC | STATIC |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| images          | https://images.linuxcontainers.org       | simplestreams | none        | YES    | NO     |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| local (default) | unix://                                  | lxd           | file access | NO     | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | simplestreams | none        | YES    | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | simplestreams | none        | YES    | YES    |
+-----------------+------------------------------------------+---------------+-------------+--------+--------+

images内にどんなイメージがあるか見てみます。

~$ sudo lxc image alias list images:

めっちゃ出てきますね。。。。
今回は、ubuntu 20.04のcloud対応イメージを使いたいので検索してみます。

~$ sudo lxc image alias list images:ubuntu/20.04/cloud
+----------------------------+--------------+-----------------+-------------+
|           ALIAS            | FINGERPRINT  |      TYPE       | DESCRIPTION |
+----------------------------+--------------+-----------------+-------------+
| ubuntu/20.04/cloud         | 79d1b80de78b | CONTAINER       |             |
+----------------------------+--------------+-----------------+-------------+
| ubuntu/20.04/cloud         | b76405f72d76 | VIRTUAL-MACHINE |             |
+----------------------------+--------------+-----------------+-------------+
| ubuntu/20.04/cloud/amd64   | 79d1b80de78b | CONTAINER       |             |
+----------------------------+--------------+-----------------+-------------+
| ubuntu/20.04/cloud/amd64   | b76405f72d76 | VIRTUAL-MACHINE |             |

手動で一つ立ち上げてみましょう。(ubuというコンテナ名でubuntu/20.04/cloudイメージで立ち上げ)

~$ sudo lxc launch images:ubuntu/20.04/cloud ubu
~$ sudo lxc list
+-------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| NAME  |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+-------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| ubu   | RUNNING | 10.246.9.113 (eth0) |fd42:6aab:85bc:47ba:216:3eff:fe98:1c93 (eth0)  | CONTAINER | 0         |
+-------+---------+---------------------+-----------------------------------------------+-----------+-----------+

コンテナのIPアドレスは、コンテナ向けプライベートアドレスから勝手に割り振られます。(僕の環境ではIPv4 10.246.9.xxx)
コンテナ向けのアドレスの確認方法は次のようになります。(ブリッジインタフェースのlxdbr0を確認する)

~$ sudo lxc network show lxdbr0
config:
  ipv4.address: 10.246.9.1/24
  ipv4.nat: "true"
  ipv6.address: fd42:6aab:85bc:47ba::1/64
  ipv6.nat: "true"
description: ""
name: lxdbr0
type: bridge
:

この出来上がったコンテナに入る方法は、lxcコマンド経由か、ネットワーク経由になります。
作ったばかりではsshの設定ができていないので、最初はlxcコマンド経由でコンテナに入り、そこで各種セットアップ作業を行うことになります。

~$ sudo lxc exec ubu bash
root@ubu:~# ls
root@ubu:~#

後は、aptでopenssh-server入れてssh設定を行えばssh 10.246.9.113といったコマンドで接続できるようになります。
次のセクションでは事前設定付きでコンテナを立ち上げるので、現在のコンテナを消しておきましょう。

~$ sudo lxc stop ubu
~$ sudo lxc delete ubu

cloud-initを使ったLXDコンテナ作成時の事前設定

Ubuntuのcloudイメージはcloud-initと呼ばれるコンテナの最初の起動時に設定を自動で行ってくれる便利な機能に対応しています。
そこで、LXDコンテナ作成時にすぐにssh接続できるように初期設定をcloud-initを使って投入します。

方法1: LXD profileを利用する

LXDでコンテナ作成する場合、通常は「default」プロファイルというlxd initで作成したプロファイルが利用されますが、別のプロファイルを作成することも可能です。以下のコマンドで作成、編集ができます。

~$ lxc profile create cloud-profile #作成
~$ lxc profile edit cloud-profile   #編集

編集する内容を以下のようにするとssh接続が自動でできるようになります。

 config:
   user.user-data: |
       #cloud-config
       hostname: ubu
       locale: ja_JP.utf8
       timezone: Asia/Tokyo
       package_upgrade: true
       package_reboot_if_required: true
       users:
           - name: hoge
             uid: 1000
             sudo: ALL=(ALL) NOPASSWD:ALL
             shell: /bin/bash
             ssh_authorized_keys:
	           - <host pcのssh pub key >
       packages:
           - openssh-server
description: my default container
devices:
    eth0:
        name: eth0
        network: lxdbr0
        type: nic
    root:
        path: /
        pool: default
        type: disk
        name: cloud-profile
 used_by: []

作成したプロファイルでコンテナを作成する場合は-p プロファイル名を付けます

~$ sudo lxc launch images:ubuntu/20.04/cloud ubu -p cloud-profile

コンテナが出来上がったらsshしてみましょう。

~$ sudo lxc list
+--------+---------+---------------------+-----------------------------------------------+-----------+-----------+
|  NAME  |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+--------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| ubu    | RUNNING | 10.246.9.174 (eth0) | fd42:6aab:85bc:47ba:216:3eff:febb:2c51 (eth0) | CONTAINER | 0         |
+--------+---------+---------------------+-----------------------------------------------+-----------+-----------+
~$ ssh 10.246.9.174
The authenticity of host '10.246.9.174 (10.246.9.174)' can't be established.
ECDSA key fingerprint is ......

さらに別の方法を試します。一旦、今のコンテナを消しましょう。

~$ sudo lxc stop ubu
~$ sudo lxc delete ubu

方法2: コンテナ作成時にcloud-initのyamlファイルを読み込ませる

この方法はコンテナをデフォルトで作成(ただし、作成するだけで立ち上げない)、その後、cloud-initを読み込ませる方法です。

~$ sudo lxc init images:ubuntu/20.04/cloud ubu  #launchではなくinitを使う
~$ lxc config set ubu user.user-data - < lxd-cloud-config.yaml
~$ lxc start ubu

ここで読み込ませるlxd-cloud-config.yamlは、以下のようなファイルです。

#cloud-config
hostname: ubu
locale: ja_JP.utf8
timezone: Asia/Tokyo
package_upgrade: true
package_reboot_if_required: true
users:
users:
    - name: hoge
      uid: 1000
      sudo: ALL=(ALL) NOPASSWD:ALL
      shell: /bin/bash
      ssh_authorized_keys:
        - <host pcのssh pub key >
packages:
    - openssh-server

方法1と同じことをしているのですが、yamlが外部ファイルにある方が管理はしやすいかもしれません。

LXDのいろいろな設定

LXDホストとファイル共有

LXDコンテナとホストでファイル共有するためには、お互いが同じuid/gidを使うアカウントが必要になります。
今回cloud-initでuid: 1000をしていしてuserを作成していますが、ubuntuでは初期ユーザが1000番になるため、それを利用します。
まず、ホストとコンテナで同じidになっているか確認します。

~$ id
uid=1000(hoge) gid=1000(hoge) groups=1000(hoge)...
~$ ssh 10.246.9.174
hoge@ubu:~$ id
uid=1000(hoge) gid=1000(hoge) groups=1000(hoge)

同じidになっているので、host/containerで共通だということを知らせる設定をします。
さらにディスクをシェア設定します。

~$ sudo lxc config set ubu raw.idmap 'both 1000 1000';
~$ sudo lxc config device add ubu my_share disk source=/data/my_share path=/my_share;

これでホスト側/data/my_shareにおいたファイルがコンテナ側/my_shareで共有されます。

LXDホストの外部インタフェースへの接続

ホストの外部インタフェース(例:192.168.0.10)のポート(例:8080)に来た接続をコンテナ(例:10.246.9.10)のポート(例:8888)につなぎたいといった場合の設定です。
lxcのproxy機能を使います。

 # lxc config device add <container> <proxy name> proxy listen=tcp:<host ip>:<host port> connect=tcp:<container ip>:<container port> bind=host
lxc config device add ubu http8080 proxy listen=tcp:192.168.0.10:8080 connect=tcp:10.246.9.10:8888 bind=host

この方法を使うと、外部からのsshを転送したり、webサービスを外部に公開したりできるようになりますね。

LXDコマンドまとめ:チートシート

LXDのコマンドはlxcです。よく使うコマンドの一覧を載せておきます。

コマンド 意味
lxc list 現在のコンテナの一覧
lxc start <container> containerを起動
lxc stop <container> containerを停止
lxc delete <container> containerを削除
lxc profile list profileの一覧
lxc profile create <profile> profileを作成
lxc profile edit <profile> profileを編集
lxc profile delete <profile> profileを削除
lxc launch <image> <container> -p <profile> imageとprofileを使ってcontainerを作成、起動
lxc init <image> <container> -p <profile> imageとprofileを使ってcontainerを作成
lxc network list ネットワークの一覧
lxc network <interface> ネットワークinterfaceの詳細
lxc storage list ストレージのリスト
lxc exec <container> bash containerに入ってbash起動。その後container内作業可能
lxc file push <local file> <container>/path/of/container/ local fileをcontainerの/path/of/container/にコピー
lxc remote list イメージリポジトリの一覧
lxc image alias list <repo>:<search> repoリポジトリの中のsearchに一致するイメージをリスト
lxc config device add/set/delete <container> containerにデバイス(network, storage等)を追加・変更・削除する

LXDコンテナは最強の開発環境

特定のバージョンの特定のOSでいつでも開発環境を作ったり消したりできる便利さを体験できると、今までの環境がいろいろなモジュールで汚れた環境に見えてきます笑
ようこそLXDの世界へ!

|

お気に入りサイト