PC上の自分用Ubuntu日本語デスクトップ開発環境サービスを作る(Vagrant+VirtualBox)

本記事では、Windows10 PC上のVirtualBoxとVagrantを利用し、開発環境の構築作業と利用を明確に分離することで、開発に必要な時だけ仮想マシンを利用するようなUbuntu日本語デスクトップ開発環境サービスを考えます。

【目次】

[1]はじめに

開発系の仕事をこなしていくと、現在開発中のものからメンテナンス期のものまで、いろいろな開発環境が必要になってきます。それぞれの開発環境は、OSレベルの違いから、開発言語、ミドルウェア、そしてそれらのバージョンも異なることもありますし、開発中の製品でも複数の製品バージョンが存在したりします。

ちなみに、ここでいう開発環境とは、個別のコード管理やビルド、テストツールというより、開発者がプログラムの作成やデバッグ、テスト実行を行ったり、様々なツールを利用できるローカルPC上のデスクトップ環境のことです。

今の時代(あるいはプロジェクト)が求める要求に応じた技術を利用するためには、今の開発環境が必要になります。一歩先の技術を知るためには、今とは異なる環境が必要になるかもしれません。さらに、過去のプログラムのメンテナンスや移行を行うために、過去の開発環境を再現したくなります。

開発環境は時代や要求に応じて変わってくるものと思いますので、結果として多様な開発環境を管理する方法が欲しくなります。

皆さんは、このような複数の開発環境をどのように管理されているのでしょうか?

私はWindows上で開発を行っており、プロジェクト毎に開発環境をVirtualBoxの仮想マシンに作りこむことで対応してきました。(今思い出しましたが、昔はWindowsにVirtualPCという仮想環境もありました。私はVirtualBox派?でしたけど。そのVirtualBoxも今はOracle社製ですが、その前はSun Microsystems社製でした。。。)

仮想化技術は、昔と違って選択肢が多く、時代とともに進化します。
せっかくブログを書き始めたので、(今までの整理も兼ねて)現在の自分の開発環境の作り方を記事として残しておくことにしました。そして、自分の開発環境が変わった時に(もうすぐ変わるかもしれませんが)、また記事を書いて、どのように移り変わっていくのかを楽しみたいと思います。

ということで、本記事から何回かに分けて、Windows 10上でVirtualBox+Vagrantを利用した自分用Ubuntu日本語デスクトップ開発環境サービスについて書いていきます。

[2]開発環境のサービス化へ

具体的な開発環境を考える前に、これまでの自分の開発環境に対する考え方(意識)の変化について振り返っておきたいと思います。

(1)「モノ」から「コト」へ?

以前は、プロジェクト開始時に、VirtualBoxの仮想マシンを新規作成し、ISOイメージからOSをインストールして、デスクトップ開発環境を作りこんでいました。一度作ってしまえば、後生大事に?その開発環境を使い続けるタイプでした(笑)。

OSのインストールから構築していた理由は、再現手順を確実にしたい、動作環境をできるだけ把握しておきたい、などでした。実際に低レベルから環境構築を行うことは、技術の理解が進み、ノウハウの蓄積にもなりました。

一方で、近年、動作環境にPaaS系などのサービスを利用するようになると、そもそもOSのレイヤ自体が見えなくなっているため、こういった細部を気にする必要がなくなりました。まだDockerなどのコンテナを利用する場合はOS色が残りますが、Google AppEngineやFunctionsのようなソースコードレベルでプロビジョニングできる環境では、OSレベルはほぼ圏外です。

そういったこともあり、土台となるOSレイヤに対する意識は薄れて、出来合いのものでもよいので、必要な開発環境が簡単に利用できることを重視するようになりました。

最近「モノからコトへ」といわれますが、手間暇かけて作った開発環境を「モノ」として重視いていたのに対して、開発環境の利用を「コト」として重視するようになったと考えると、同じような流れという気がします。

(2)必要な時だけ使える開発環境

当初はOSレベルからのインストールに大きな不満があったわけではないのですが(というより、そういうものだと思っていましたが)、課題は感じていました。
  • プロジェクト開始時に、仮想環境へISOイメージからOSの基礎的なデスクトップ環境を整え、Guest Additionsをインストールし、ミドルウェア等をインストールし、言語やIDEをセットアップし、などなど、インフラ的なことにあまり興味のない私には苦行でした(涙)。
    • プロジェクト開始時は技術構成が固まっていないことが多いため、試行錯誤が多く、そうこうしていると構築手順を失念したり。。。
  • 安定した開発環境ができて、安定して作業ができるようになると、ツールなどの新しいバージョンをちょっと試そうという気になれませんでした。
    • スナップショットの機能やバックアップはありますが、後で本当に戻す必要がある時点のものを取っていなかったり、エクスポート+インポートで別のVMを作るのにも案外時間や手間がかかることが多かったりしました。

その後、Vagrantとか、Chefなどのインフラ構築ツールが登場し、これらを導入しようと考えたこともありましたが、以前はスクラッチから環境を作ることに価値を感じていたため、移行しませんでした。

そしてDaaS(Desktop as a Service)が流行り始めたと時も目移りしましたが、(導入コストや管理コストは別として、)自分が自由に構築や管理ができる開発環境とは趣が異なる気がしていました。

そんななか、Google Colaboratoryに出会いました。

これは私にとってはかなり衝撃的でした。何が衝撃的だったかというと、Jupyter Notebookが無料で使えることもありますが、仮想マシンを無料で割り当ててくれることでした。

DaaSはOSのデスクトップ環境を提供してくれますが、Google Colaboratoryは、UIがOSのデスクトップからJupyter Notebokになったデスクトップサービス(DaaS)という印象です。利用したいときに、WordやExcelを使うのと同じくらい簡単に、新しい環境(Notebook+仮想マシン)を提供してくれます。

ここでとても興味深いのは、Notebookを開くと、必要に応じて自動的に仮想マシンを割り当ててくれて、使い終わったら自動的に破棄されることです。つまり、必要な時だけ仮想マシンが割り当てられており、サービス的な感覚を覚えました。
(ちなみに、Wikipediaによると、サービスとは「経済用語において、売買した後にモノが残らず、効用や満足などを提供する、形のない財のことである。第三次産業が取り扱う商品である。」と説明されています。)

こういう世界を知ると、自分のデスクトップ開発環境も、同じようにサービスっぽく構築(必要な時にだけ簡単に使える)したいと思うようになりました。
例えば、必要になったら自分好みのIDEやデータベースが揃っている仮想マシンを素早く準備して、リポジトリからソースコードをダウンロードして開発し、使い終わったら終わったら仮想マシンを破棄する、という利用形態です。こうなってくると、先のような課題も解決できそうです。

[3]ローカルPC上のサービス実現技術(Vagrant+VirtualBox)

クラウドサービスの利点の一つは、必要な時だけ仮想マシンを利用できることです。また、仮想マシンを作成する際に、既に作りこんでいる仮想イメージを利用することもできます。
これと同じようなことをローカルPCで実現しようと考えたとき、まっさきに思いついたのがVagrantでした。(以前はスルーしてしまったんですが。。。)
Vagrant Cloud(https://app.vagrantup.com/boxes/search)で様々なベースBOXが提供されており、これをもとに簡単に仮想マシンを構築できます。さらに、仮想マシンからBOXを簡単に作ることもできます。

VirtualBox単体の利用に対して、VirtualBoxとVagrantと組み合わせた場合の利点や欠点(制約)をみておきます。

(1)VagrantのBOXを利用して環境構築する利点

  • ベースBOXをVagrantfileでカスタマイズして仮想マシンを作成できます。
    • 仮想マシンは、設定やプロビジョニング情報を記述したVagrantfileにしたがって作成されます。これを利用して、元となるBOXへのカスタマイズ(環境構築)を、ある程度自動化することが出来ます。(完全ではありませんが、)Vagrantfileを初期設定の手順書のように利用することもできます。
    • Vagrantfileを再利用することで、同じ仮想マシンを簡単に作成できます。これは、複数の同じ仮想マシンを同時に作成するようなシナリオにも利用できますが、仮想マシンを破棄して再生というサービス的なシナリオにも利用できます。
  • BOXを自分で作ることができます。
    • OSレベルのベースBOXから、自分がカスタマイズして自分用のBOXを簡単に作ることが出来ます。あらかじめよく利用するBOXを作成しておくことで、仮想マシン作成から利用までのサイクルをかなり短縮できます。
    • なお、Packerなどを利用して作りこむ方法もありますが、本記事とは趣旨が異なりますので、割愛します。
  • OSの基本設定が行われています(一定の標準化が行われています)。
    • Vagrantのガイドラインに沿って、OSからクリーンインストールするときに選択する項目などが設定されています。ユーザアカウントなども設定済みです。
  • Guest Additionsが予め組み込まれています。
    • 仮想マシンで共有フォルダ、UIのリサイズ、クリップボード共有などの拡張機能を利用するためにはGuest Addtionsをインストールする必要がありますが、これが予め組み込まれているのは、思ったより便利でした。
  • コマンドプロンプトから簡単なコマンドで操作できます。
    • VirtualBoxのようにユーザインターフェイスはありませんが、コマンドプロンプトから、よく整理されたVagrantコマンドだけで操作できます。(人によっては欠点かも?)

(2)Vagrantを利用する欠点?

  • Vagrantの使い方を知る必要があります。
    • Vagrantの(高度なことを考えなければ)とても分かりやすいツールだと思います。さらに丁寧な公式ドキュメントもあります(但し、英語ですが)。日本語の情報はネット上に沢山あります。
    • Vagrant Documentation(https://www.vagrantup.com/docs
  • VirtualBoxに比べると制限があります。
    • VagrantのBOXの作成要件として一定の基準(ガイドライン)があります。例えば、SSH、Guest Additions、vagrantユーザ等々、一定の要件があるので自由度は制限されます。しかし、これは自動化や標準化とも関係するため、欠点ばかりではありません。
    • ベースBOX作成時の要件については、以下のURLに記載があります。

[4]自分用開発環境サービス

PC上でサービス的な開発環境の流れと、それを構成できる技術(VirtulBox+Vagrant)を見てきました。あとは、これをどのように利用、運用するか、を考えるだけになります。

ところで、サービスは利用する側と提供する側があります。自分用サービスということは、自分が利用すると同時に、自分が提供する側にもなります。
そこで、自分なりの利用シナリオ(要求仕様的なもの)を少し明確にしたうえで、それを提供する方法を見ていきます。

(1)サービスを利用する側(開発作業)のシナリオ

目標とする開発環境サービス像を考えるために、まず、開発作業を行う具体的な利用シナリオを考えます。

①新規開発のとき、あるいは一時的に実験などを行いたいとき

  1. 開発に必要な開発環境(IDE、ミドルウェア、その他開発ツール一式)が揃ったBOXのカタログを選択して、プロジェクト用の仮想マシンを作成します。
    • このとき、実際の開発マシンなどの状況など、必要に応じてCPU、メモリ、ネットワーク、共有設定などの具体的な設定をVagrantfileに記述して仮想マシンを作成します。
  2. プロジェクト用の仮想マシンで開発を行います。
    • 成果物となるソースコードなどはリポジトリや共有フォルダなどの仮想マシン外で管理します。
  3. 開発が終了したら、Vagrantfileなどのプロジェクトの環境設定や成果物などを保存して、仮想マシンを破棄します。

②継続開発のとき

  1. 前回開発に使用したVagrantfileなどの環境設定を元に、プロジェクト用の仮想マシンを作成します。
    • あるいは、要求される環境が異なるような場合は、新規の場合と同様に新たにBOXを選択して仮想マシンを作成します。
  2. 前回の成果物をリポジトリやバックアップから復元して、プロジェクト用の仮想マシンで開発を行います。
    • 成果物となるソースコードなどはリポジトリや共有フォルダなどの仮想マシン外で管理します。
  3. 開発が終了したら、Vagrantfileなどのプロジェクトの環境設定や成果物などを保存して、仮想マシンを破棄します。
①と②で場合分けして書きましたが、違いは仮想マシンの作り方(選び方)のみです。

どちらにしても、仮想マシンは必要な時(開発作業を行っている時)のみインスタンス化して、不要になれば破棄することになります。

基本的にはプロジェクトが終了するまで仮想マシンを利用すると思いますが、例えば、プロジェクト途中でツールのバージョンアップを行うような場合は、新しいツールが揃ったBOXから仮想マシンを作成して、そちらに移行するような運用になると思います。

(2)サービスを提供する側(BOX作成)の考え方

開発を行う作業は大きく分けると、
  • (A)プロジェクト用の開発環境(ミドルウェア、開発ツールなど一式)の構築作業
  • (B)構築済みの開発環境で、コーディング、テストなどの開発作業
になると思います。

このうち(B)は利用側のシナリオそのものですので、サービスを提供する側の作業としては(A)ということになります。
また、利用側の(B)の作業は、開発環境が構築されたBOXから仮想マシンを作成して行いますので、(A)の作業は、自分が必要とする開発環境がセットアップされたVagrantのBOXを作成することになります。

Vagrant Cloudなどに自分にぴったりのBOXがあれば、それを利用すればよいのですが、必要な開発ツールの種類やバージョンまでそろったBOXはなかなかないと思います。また、ある程度ツールの種類やバージョンも自分で把握、コントロールしたいものでもあります。
一方で、VagrantのベースBOXの要件を満たすようにスクラッチからBOXを作るのも骨が折れます。

そこで、ベースBOXの要件を満たしながら、自分が必要とする開発環境を効率よく作る方針を以下のように考えました。
  • BOXにインストールする開発ツールなどはレイヤー(あるいはクラス)分けし、オブジェクト指向プログラミングでいうクラス継承のような感じで、下位レイヤーのBOXから上位レイヤーのBOXを作成するようにします。
    • ここで、Vagrantfileには、ベースBOXの要件を維持するように、Vagrantfileにはプロビジョニングを除いて必要最小限の項目のみ設定します。
  • 最下位レイヤーのBOXは、Vagrant Cloudが提供しているベースBOXから作成します。

このように段階的に積み上げ方式でBOXを作成することにより、BOXの作成効率を上げることに加えて、利用側の選択肢を増やします。また、ベースBOXの要件を極力守ることで、他のPCで再利用する際などのトラブルも軽減できると思います。

ここで、開発ツールなどのレイヤーあるいはクラス分けは概念的なものですので、その組み合わせ毎にBOXを作る必要はありません。例えば、Vagrantfileのプロビジョニングに設定すれば素早くインストールできるものは、開発用仮想マシン作成時のVagrantfileに記述できます。
現実問題として、BOXの数が多くなると管理不能になるため、よく利用するパターンに応じて大雑把に分ける程度が良い気がします。
私の場合は、基本的には、小さくてaptで素早くインストールして使えるものはVagrantfileに記述することにして、インストールに時間がかかるものやユーザインターフェイスからでないと設定できないようなものはBOXに組み込む、という感じです。
継続的なプロジェクトでは、ツールのバージョンなどを固定したいこともあり、専用のBOXを作ることにしています。

(3)サービスを提供する側(BOX作成)の作業手順

以下に具体的なBOXの作成手順を書きます。
  1. 元にするBOXからBOX作成用仮想マシンを作成します。
    • 既存の自作BOXが利用できる場合は、そのBOXから作成します。それ以外(最下位レイヤのBOXなど)は、Vagrant Cloudが提供しているベースBOXから作成します。
    • ベースBOXの要件を維持するように、Vagrantfileにはプロビジョニングを除いて必要最小限の項目のみ設定します。(ネットワークや共有設定など、具体的な実行環境に依存する設定は行わないようにします。これらの設定は利用側のVagrantfileで必要に応じて設定するようにします。)
  2. プロビジョニングでインストールや設定ができない項目については、BOX作成用仮想マシン内で必要なツールなどのインストールや設定を行って、開発環境を整えます。
  3. BOX作成用仮想マシンの開発環境が整ったら、パッケージ化してBOX登録します。

なお、BOX登録後は、Vagrantfileや作成手順などを残したうえで、BOX作成用仮想マシンそのものは破棄しても問題はないと思います。
例えば、BOX作成用仮想マシンの内容を少し修正したい場合は、登録したBOXから仮想マシンを作成して、必要な作業後に再度BOX登録します。あるいは、もとのVagrantfileを編集して新たなBOX作成用仮想マシンで構築して、異なるBOXとして登録することもできます。

(4)要点のまとめ

サービスといいつつも、提供側と利用側のどちらも「自分」ですので、ここまでの要点を整理しておきます。
  • 開発環境を整える作業(開発環境BOXの作成)と、それを利用した開発作業(仮想マシンの利用)に分けて考えます。
    • 開発作業に必要となるツールや環境の整備は、開発環境BOXを作成する作業と考えます。開発環境BOXから作った開発作業用の仮想マシンでは、成果物を作ることに集中して、開発環境の変更は行わないようにします。
    • 開発環境BOXは、段階的に作成することで再利用しやすいようにします。
  • VirtualBoxの仮想マシンは使い終わったら破棄することを前提に考えるようにします。
    • 仮想マシンイメージはファイルサイズが大きいので、破棄できればディスクの節約になります。また、VirtualBoxの仮想マシン一覧もすっきりします。
    • 破棄することを意識すると、何をどこに残しておきたいかや、それを元に環境を戻すには何が必要か、が明確になることがありますので、開発環境BOXの内容や成果物の管理に意識がいきやすいと思います。
  • Vagrantfileの記述内容について
    • BOX作成用仮想マシンの場合(サービス提供側)
      • ベースBOXの要件を維持するように、Vagrantfileにはプロビジョニングを除いて必要最小限の項目のみ設定します。(ネットワークや共有設定など、具体的な実行環境に依存する設定は行わないようにします。)
    • 開発作業を行う仮想マシンの場合(サービス利用側)
      • 実際の開発マシンなどの状況など必要に応じてCPU、メモリ、ネットワーク、共有設定などの具体的な設定をVagrantfileに記述します。

[5]Ubuntu日本語デスクトップ開発環境サービス

(1)概要

自分用開発環境サービスの具体例として、Ubuntuの日本語デスクトップ開発環境サービスの運用フローを考えます。
なお、今回はUbuntuを例にしていますが、他のOSでも同様に考えられると思います。(私はもともとCentOSを利用していましたが、Google ColaboratoryがUbuntuだったことがきっかけで、今回はUbuntuで記事を書きました(笑)。)

概略を図にすると以下のようになります。

VirtualBox+VagrantでUbuntu日本語デスクトップ開発環境サービスを構成するフロー


私はVagrantのプロジェクトフォルダ(Vagrantfileがあるフォルダ)を以下のように構成して利用しています。
  • c:\vagrant\
    • boxes\
      • BOX作成用のVagrantプロジェクトフォルダを作成します。
    • projects\
      • 開発作業用のVagrantプロジェクトフォルダを作成します。
  • c:\vmshare
    • 仮想マシン共通で利用する共有フォルダです。バックアップやファイルの受け渡しなどに利用します。

ここで、上記vagrant以下のフォルダは、仮想マシンを使い終わったら、vagrant destroyとバックアップを行ってから削除できます。

以下に、大雑把なフローを書いてきます。

(2)UbuntuのベースBOXから日本語デスクトップ環境のBOXを作成する

まずは、ベースBOXに日本語のデスクトップ環境を追加したBOX(図では+GUI Box)を作成します。
これは日本語デスクトップ環境の最下位レイヤーのBOXとして作成するため、開発ツールなどはインストールしません。
  1. c:\vagrant\boxesの下に、GUI BOX作成用のプロジェクトフォルダを作成します。
  2. Vagrant CloudからUbuntuのベースBOXを指定して仮想マシンを作成します(vagrant up)。
    • Vagrantfileのプロビジョンに、デスクトップパッケージのインストールなどを記述します。但し、ネットワークなどの環境固有の設定は変更しません。
  3. 仮想マシン内で日本語環境を利用できるように調整します。
  4. 日本語環境が整ったら、仮想マシンの内容をパッケージ化します(vagrant package)。
  5. 作成したパッケージをBOX登録します(vagrant box add)。
  6. (オプション)VirtualBoxの仮想マシンを破棄し(vagrant destroy)、プロジェクトフォルダをバックアップした上で、フォルダを削除します。
    • ここで、作成したパッケージ(package.box)もバックアップしておくと、登録したBOXのバックアップになるのと同時に、他のマシンでBOX登録するためのパッケージとしても利用できます。

(参考)
上記の具体的な手順を別記事で書きましたので、参照してください。

(3)日本語デスクトップ環境のBOXから開発ツールを追加したBOXを作成する

先に作成した日本語のデスクトップ環境のBOXから、開発ツールなどを追加したBOX(図では+DevTools Box)を作成します。
  1. c:\vagrant\boxesの下に、DevTools BOX作成用のプロジェクトフォルダを作成します。
  2. 先に作成した日本語デスクトップ環境のBOXをベースBOXとして仮想マシンを作成します(vagrant up)。
    • Vagrantfileのプロビジョンに、ミドルウェアや開発ツールなどのインストールを記述します。但し、ネットワークなどの環境固有の設定は変更しません。
  3. 必要に応じて仮想マシンで開発環境の調整します。
  4. 開発環境が整ったら、仮想マシンの内容をパッケージ化します(vagrant package)。
  5. 作成したパッケージをBOX登録します(vagrant box add)。
  6. (オプション)VirtualBoxの仮想マシンを破棄し(vagrant destroy)、プロジェクトフォルダをバックアップした上で、フォルダを削除します。
    • ここで、作成したパッケージ(package.box)もバックアップしておくと、登録したBOXのバックアップになるのと同時に、他のマシンでBOX登録するためのパッケージとしても利用できます。

(参考:2022/10/22追記)
BOX化しない方法も書いてみました。

(参考:2021/12/06追記)
具体例を書きましたので、よかったら参考にしてください。

(4)BOXから開発用仮想マシンを作成して開発作業を行う

先に作成したBOXを利用して開発用仮想マシンを作成して開発作業を行い、開発が終わったら破棄します。
  1. c:\vagrant\projectsの下に、開発作業用のプロジェクトフォルダを作成します。
  2. ベースBOXとして作成済みのBOXを指定して仮想マシンを作成します(vagrant up)。
    • Vagrantfileには、実際の開発マシンなどの状況など必要に応じてCPU、メモリ、ネットワーク、共有設定などの具体的な設定を記述します。
  3. プロジェクト用の仮想マシンで開発を行います。成果物となるソースコードなどはリポジトリや共有フォルダなどの仮想マシン外で管理します。
  4. 開発が終了したら、プロジェクトフォルダをバックアップした上で、仮想マシンを破棄(vagrant destroy)します。

なお、適当な開発環境BOXがない場合は、(今後利用しそうなものについては)必要に応じて、新たに開発環境BOXを作成してから上記手順を実行します。

ところで、段階的にBOXを作成しておくと、便利な場合もあります。
例えば、LibreOfficeなどデスクトップ環境に組み込まれているツールを利用したいだけなら、日本語デスクトップ環境のBOXがそのまま利用できます。
また、aptなどで簡単にインストールできるソフトウェアを追加するだけであれば、作成済みのBOXから、開発用仮想マシン作成時にVagrantfileのプロビジョンに設定するだけで利用できると思います。

本格的なプロジェクトで内容を固定したい場合は、プロジェクト専用のBOXを作成して利用するのがよいと思います。

コメント

このブログの人気の投稿

VirtualBoxのスナップショット機能

Google Document AIで画像から表形式データを抽出する(Vision API OCRとの違い)

Ubuntu/Colab環境でPDFファイルのページを画像化する(pdf2image、pdftoppm、pdftocairo)