ファイルバックアップ用ディスクを用意する(パーティションの作成とファイルシステムの作成)

  • 現在、プライベートでとった写真などのファイルは外付けのHDDに格納するようにしていますが、バックアップを取っていないのでなんとかしたい
  • バックアップに使えそうなHDDが余っていたので、まずは取り急ぎそのHDDにコピーするところから始める
  • ちょうどLPIC201でストレージ管理周りの問題がでるので、学習を兼ねてCLIでやっていく

手順は学習用に用意したHDD(4G)で試していきます。

外付けHDDを差す

/dev/sdb にいることを確認

sudo fdisk -l
ディスク /dev/sdb: 4 GiB, 4327464960 バイト, 8452080 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト

パーティションを確認する

特に設定されてなさそうなので、新しく作成していく。

sudo gdisk -l /dev/sdb

パーティーションの方式は、特に古い方式であるMBRにする理由はないのでGPTにしておきます。

GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries.
Disk /dev/sdb: 8452080 sectors, 4.0 GiB
Model: MK4310MAT
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 8452046
Partitions will be aligned on 2048-sector boundaries
Total free space is 8452013 sectors (4.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name

パーティションを作成する

sudo gdisk /dev/sdb

GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries.

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-8452046, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-8452046, default = 8452046) or {+-}size{KMGTP}:
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdb.
The operation has completed successfully.

ファイルシステムを作成する

ファイルシステムはメインPCに合わせてext4にしました。

sudo mke2fs -t ext4 /dev/sdb1

mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 1056249 4k blocks and 264528 inodes
Filesystem UUID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information:
done

ファイルシステムと不良ブロックのチェックする

sudo e2fsck -c /dev/sdb1

-cbadblocks を使って不良ブロックをチェックします。 見つかった不良ブロックはファイルやディレクトリとして確保されないようになります。

e2fsck 1.44.1 (24-Mar-2018)
Checking for bad blocks (read-only test):   0.00% done, 0:00 elapsed. (0/0/0 errdone
/dev/sdb1: Updating bad block inode.
Pass 1: Checking iノードs, blocks, and sizes
Pass 2: Checking ディレクトリ structure
Pass 3: Checking ディレクトリ connectivity
Pass 4: Checking reference counts
Pass 5: Checking グループ summary information

/dev/sdb1: ***** ファイルシステムは変更されました *****
/dev/sdb1: 11/264528 files (0.0% non-contiguous), 37125/1056249 blocks

動作確認

sudo mkdir /mnt/disk sudo mount -t ext4 /dev/sdb1 /mnt/disk

cd /mnt/disk/
sudo touch test
ls test
test

書き込めたので良さそう。

次回は、バックアップしたいファイルをコピーして行こうと思います。

Kubernetesでの開発を楽にするskaffoldを使ってみる

Kubernetesを開発環境で使っていると、 コードを修正して確認する度に、imageを作り直し、Kubernetesへデプロイしなければならないため、開発効率がよくありません。 hostPathをマウントする方法で解決できますが、Kubernetesでは、マウントパスを絶対パスで記述しなければならないため、manifestを共有しチームで開発しようとすると、各々の環境に合わせてパスを設定し直さなければなりません。

上記のような問題を解決するツールである skaffold というのを見つけたので試してみます。

どういったものか

  • ファイルの変更を検知して、イメージのビルド・プッシュ・デプロイを自動で行ってくれる
  • Google製(GoogleContainerTools)
  • Kubernetesサーバ側に何か設定する必要はない

参考

検証環境

環境は以下です。

  • PC: Ubuntu18.04
  • Kubernetes環境: minikube(virtualbox
  • 管理コマンド: kubectl
  • アプリケーション: 標準的なrailsアプリ

事前準備

skaffoldのインストール

以下の手順でインストールします。 https://skaffold.dev/docs/getting-started/

dockerの設定

minikubeのdockerを使います。

eval $(minikube docker-env)

設定する

skaffoldの設定ファイルである skaffold.yaml を設定します。 skaffold init というコマンドを実行すると、Kubernetesのmanifestを見て自動的に skaffold.yaml を生成してくれます。

apiVersion: skaffold/v1beta9
kind: Config
build:
  artifacts:
  - image: rails_app
deploy:
  kubectl:
    manifests:
    - rails-deployment.yaml
    - rails-service.yaml

ちなみに、manifest ファイルは以下のような感じです。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: rails
spec:
  replicas: 1
  template:
    metadata:
      labels:
        role: app
    spec:
      containers:
      - args:
        - bash
        - -c
        - bundle exec rake db:migrate && bundle exec rails s -b # 検証用なので、いちいちdb:migrateしています。
          0.0.0.0
        image: rails_app
        imagePullPolicy: Never # minikube上にimageができるのでpullする必要ありません。
        name: rails-app
        ports:
        - containerPort: 3000
        volumeMounts:
        - mountPath: /usr/local/bundle
          name: bundle
      volumes:
      - hostPath:
          path: /tmp/bundle
        name: bundle
apiVersion: v1
kind: Service
metadata:
  name: rails-app
spec:
  ports:
  - name: "3000"
    port: 3000
    targetPort: 3000
    nodePort: 30080
  selector:
    role: app
  type: NodePort

実行する

  • skaffold dev で実行する

フォアグラウンドで待ち受けられます。

-v debug で詳細に何をやっているのかが見られるので、気になる方はこちらのオプションをつけてみても良さそうです。

  • ファイルの変更をする

適当にファイルを編集して保存すると、ビルド、デプロイが実行されました! (ブラウザで確認し、ちゃんと反映されていることも確認)

Generating tags...
 - rails_app -> rails_app:3ec4d44-dirty
Tags generated in 26.202452ms
Starting build...
Found [minikube] context, using local docker daemon.
Building [rails_app]...
Sending build context to Docker daemon  40.27MB
・・・

podも新しくなっている様子

kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
rails-7b7c8bc85b-95ljp   1/1     Running   0          21s

この方法であれば、ビルド・デプロイの手間が省けるので、不自由なく開発ができそうです!

どういう仕組みなのか?

どうやら、Dockerfileの COPY(もしかしたらADDも) の内容からどのファイルをウォッチするかを判断しているようで、 DockerfileまたはCOPYしている範囲に変更があれば、ビルド->タグ付け->デプロイを自動で行ってくれるようです。

注意点

注意点としては、Dockerfileのキャッシュを上手く利用する書き方をしていないと、ビルドする度に時間がかかってしまいます。 ソースをコピーする記述はなるべく下のほうに書いておくと良さそうです。 また、DockerfileのCOPYは、ディレクトリをさかのぼる記述は書けないので、ウォッチしたいファイルがちゃんとCOPYできるようファイル構成を考える必要があります。

以上、今日のところはこんな感じです。

docker for mac に同梱されている kubernetes を使ってみる

昨日、こちら でminikubeを使ったローカル環境の構築を行いましたが、どうやら docker for mackubernetes が同梱されているようなので、使ってみます。

インストールする

右上の dockerのマークをクリックし、 Preference を選択

f:id:takapi86:20190503192003p:plain

Kubernetes -> Enable Kubernetes にチェックを入れて、Apply をクリックすればインストールされ使えるようになります。

f:id:takapi86:20190503190942p:plain

早速デプロイしてみる

先日、こちらで、minikubeにデプロイしたアプリケーションを使います。また、今回はkomposeコマンドは使わずにyamlファイルを作成し、kubectlコマンドでデプロイするようにします。(ただ、yamlファイルはkomposeで生成したものをベースにし修正しました。)

こちらのyamlファイルを用意し、 (まだ、雰囲気で書いている段階なので冗長な箇所などがあるかも)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: rails
spec:
  replicas: 1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        group: rails
    spec:
      containers:
      - args:
        - bash
        - -c
        - rm -rf /usr/src/app/tmp/pids/server.pid && bundle exec rake db:migrate && bundle
          exec rails s -b 0.0.0.0
        image: localhost:5000/takapi/app_rails:v1
        name: rails
        ports:
        - containerPort: 3000
        resources: {}
status: {}
apiVersion: v1
kind: Service
metadata:
  name: rails
spec:
  ports:
  - name: "3000"
    port: 3000
    targetPort: 3000
  selector:
    group: rails
  type: NodePort
status:
  loadBalancer: {}

以下のコマンドでデプロイ

kubectl create -f rails-service.yaml
kubectl create -f rails-deployment.yaml

どうやらうまく行った感じがします。

kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
rails        NodePort    10.99.111.229   <none>        3000:31378/TCP   4m
kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
rails     1         1         1            1           4m
kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
rails-558944b847-4vbgv   1/1       Running   0          4m
kubectl logs rails-558944b847-4vbgv
INFO  WEBrick 1.4.2
INFO  ruby 2.6.1 (2019-01-30) [x86_64-linux]
INFO  WEBrick::HTTPServer#start: pid=1 port=3000

そして、localhost:31378 にアクセスすると、アプリケーションのページが表示されるようになりました!

ソースファイルをマウントしてみる

minikubeと違い、ホストはmacなので(もちろん、dockerを動かすためのVMはいますが)普通にVolumeマウントができます。

ということで、 rails-deployment.yaml に以下に追記し、

         ports:
         - containerPort: 3000
         resources: {}
+        volumeMounts:
+          - name: app-src
+            mountPath: /usr/src/app
+      restartPolicy: Always
+      volumes:
+        - name: app-src
+          hostPath:
+            path: /Users/takapi/app
+            type: Directory
 status: {}

再デプロイします。

kubectl delete deployment rails
deployment.extensions "rails" deleted
kubectl create -f rails-deployment.yaml
deployment.extensions "rails" created

ファイルを編集するとリアルタイムで変わったので、マウント成功!

まとめ

現時点でやってみた感じでは、minikubeもdocker for macもどちらも大きく操作が異なるという訳ではありませんした。 なので、実際開発環境として使う際は、mac を使っている人は、docker for mac で良いのではないかなぁ。多分。と思う今日の頃。

minikubeの場合、ホスト側のファイルをマウントしたいときは、PC <-> minikube <-> コンテナ といった感じにマウントしなくてはならないため、PC <-> minikube のファイル共有設定に一手間必要そうです。

ちょっとだけ、Kubernetesの雰囲気が掴めてきたかもしれない。 

今日のところはこんな感じで。

ローカル開発環境として minikube + kompose を使ってみる

  • 巷ではk8sが流行っているが、そもそもどんなことができるか理解できていないので、どういったものか触ってみたい
  • 業務ではdockerを使った開発環境の導入を行っているが、複数にまたがったロールの管理がしにくいので解決したい。こういったことはk8sなら解決できるのでは?と、ふと思った。

ということから、まずは、ローカル環境でk8s環境を構築することができる minikube を使って、ローカル環境を構築してみることにしました。

今回は練習として、以前、自分で作成したrailsのアプリケーションをデプロイし動かせるようにするところまで行います。 (普通のrailsアプリケーションなので、特別な設定は必要ありません。)

デプロイする予定のアプリケーションの開発環境は、すでにdocker環境(docker-compose環境)で動くようになっています。 せっかくなので、docker-compose.ymlをk8sの設定ファイルに変換してくれる kompose というツールを使ってみようと思います。

minikubeとは?

macOSLinux、およびWindowsvirtualboxなどのVM上にKubernetesクラスタを構築できるものです。

公式サイト:

github.com

  • こちらの手順でインストールできます。

Install Minikube - Kubernetes

komposeとは?

docker-compose.yml をk8s用の設定ファイルに変換してくれるツールです。

公式サイト

Kubernetes + Compose = Kompose

(インストール方法もこちらにあります。)

まずは、チュートリアルをやってみる

そもそも、k8sの使い方がわからなかったので、以下のチュートリアルで学習しました。

Hello Minikube - Kubernetes

開発環境を作っていく

以下の記事を参考にしました。

Docker ComposeからMinikube + Komposeに移行してみよう - Qiita

hawksnowlog: kompose を使って kubernetes 上で docker-compose してみる

基本的な流れは上記の記事の通りですが、自分なりにハマった点などを次にまとめました。

クラスターを作成する

  • minikube start でminikubeを起動
    • 実行すると仮想マシンが作成されます。
    • --vm-driver で、ドライバーの種類を設定できますが、デフォルトはvirtualboxが指定されるので、virtualboxを使う人はそのままで良いです。

komposeでk8sのファイルに変換する

  • アプリケーションのディレクトリ配下で kompose convert --volumes hostPath を実行します。

すると、以下2種類のファイルが作成されました。

kompose convert --volumes hostPath
INFO Kubernetes file "rails-service.yaml" created
INFO Kubernetes file "rails-deployment.yaml" created

ちなみに、元々の構成はこうでした。 必要なものを Dockerfile でインストールして、ソースコードや設定は docker-compose.yml に書くようにしています。

  • Dockerfile
FROM ruby:2.6.1

ENV LANG=C.UTF-8 TZ=Asia/Tokyo

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir -p /usr/src/app
RUN gem install bundler
WORKDIR /usr/src/app
  • docker-compose.yml
version: '3'

services:
  rails:
    build: ./
    command: bash -c 'bundle install && bundle exec rake db:migrate && bundle exec rails s -b 0.0.0.0'
    volumes:
      - .:/usr/src/app
      - bundle:/usr/local/bundle
    ports:
      - '3000:3000'

volumes:
  bundle:

kompose でデプロイする

続いて、kompose up --volumes hostPath で、minikube にデプロイしていこうと思ったのですが、以下のエラーが発生してしまいました。

FATA Error while deploying application: k.Transform failed: image key required within build parameters in order to build and push service 'rails'

どうやら、Dockerfile の指定はできないので、一度イメージ化しDockerレジストリに登録してあげる必要があるようです。 (k8s上で使うには、環境のイメージをどこかのレジストリにpushし、そこからpullするように設定する必要があるっぽいです。)

Dockerレジストリをローカルにたて、build: ./image: localhost:5000/takapi/app_rails:v1 にし再コンバート・再デプロイ。

minikubeのdocker側にimageを作ることで、ローカルでDockerレジストリを立てる必要はありませんでした。 単純に image: にイメージの名前を指定すればOKです。

詳しくはこちらの記事をご参照ください。 minikubeでローカルのdocker imageを使う - Qiita

今度は、デプロイできたようです。

kompose up --volumes hostPath
INFO We are going to create Kubernetes Deployments, Services and PersistentVolumeClaims for your Dockerized application. If you need different kind of resources, use the 'kompose convert' and 'kubectl create -f' commands instead.

INFO Deploying application in "default" namespace
INFO Successfully created Service: rails
INFO Successfully created Deployment: rails

Your application has been deployed to Kubernetes. You can run 'kubectl get deployment,svc,pods,pvc' for details.

しかし、おや?ステータスが CrashLoopBackOff になっているようです。

kubectl get pods
NAME                     READY   STATUS             RESTARTS   AGE
rails-6747b44c87-r2tf5   0/1     CrashLoopBackOff   4          2m19s

logを見てみる

kubectl logs rails-6747b44c87-r2tf5
Could not locate Gemfile

おそらく、ファイルがマウントされていないのでしょう。 しかし、ホストからコンテナにファイルをマウントする方法がわからなかったので、今回は泣く泣くイメージにソースコードを突っ込むようにして対応します 😭

再デプロイする

コードをイメージに含めるようにし、再度デプロイ。 これで正常にデプロイ出来ました。

kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
rails-756f6f594b-mwzc5   1/1     Running   0          25m

kubectl logs rails-756f6f594b-mwzc5
INFO  WEBrick 1.4.2
INFO  ruby 2.6.1 (2019-01-30) [x86_64-linux]
INFO  WEBrick::HTTPServer#start: pid=1 port=3000
  • Dockerfile
FROM ruby:2.6.1

ENV LANG=C.UTF-8 TZ=Asia/Tokyo

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir -p /usr/src/app
RUN gem install bundler
WORKDIR /usr/src/app

COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . ./
  • docker-compose.yml
version: '3'

services:
  rails:
    image: localhost:5000/takapi/app_rails:v1
    command: bash -c 'bundle exec rake db:migrate && bundle exec rails s -b 0.0.0.0'
    ports:
      - '3000:3000'

外部から接続できるようにする

アプリケーションを外部から接続できるようにします。

kubectl delete service rails
kubectl expose deployment rails --type=NodePort

これで外部からアプリケーションのURLを叩けるようになりました。

アプリケーションを開く

以下のコマンドを叩くことによって、ブラウザが立ち上がり自動的にアプリケーションのページを開いてくれます。

minikube service rails

まとめ

この手順で、アプリケーションをデプロイすることができました。

まだ手探り状態なので、minikubeの機能かなにかでローカルファイルのマウントの方法があるのか、それとも仕組みとしてできないものなのかはまだわかっていないのですが、 仮にそもそもローカルのファイルがマウントできないのであれば、ちょっとの修正でもイメージ化->デプロイをしなければ確認ができなので、開発環境としては、ちょっと辛くなりそうだなぁという気持ちです。

調べてみたところ、良い感じに自動でやってくれる Skaffold というものがあったので、今度試してみたいと思います。 あとはこのへんなど

www.telepresence.io

以上、今日のところはこんな感じです。

外付けSSDにインストールしたgrub2からPC本体のUbuntuを起動する【LPIC201の学習】

LPIC201では、パーティションファイルシステムブートローダ周りが、101の頃より深い内容で出題されます。 このへんはあまり業務では触れない分野なので、色々試してみようと思います。

今回は外付けSSDにgrub2をインストールし、PC本体のUbuntuを起動するところまでやります。

環境

UEFIでブートするには

で、あることが条件であるため、これを満たすように設定していきます。

外付けSSDをフォーマットする

SSDを接続

dmesg で、SSDを接続が /dev/sda として認識されていることを確認

[27264.071136] usb 2-1: new SuperSpeed USB device number 15 using xhci_hcd
[27264.095562] usb 2-1: New USB device found, idVendor=13fd, idProduct=3609
[27264.095571] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[27264.095577] usb 2-1: Product: Ini-3609
[27264.095582] usb 2-1: Manufacturer: Initio
[27264.095586] usb 2-1: SerialNumber: XXXXXXXXXXXXXXXXXXXXXXXXXXX
[27264.109267] scsi host2: uas
[27264.111778] scsi 2:0:0:0: Direct-Access     Initio   Ini-3609         0302 PQ: 0 ANSI: 6
[27264.147921] sd 2:0:0:0: Attached scsi generic sg0 type 0
[27264.186853] sd 2:0:0:0: [sda] Spinning up disk...
[27265.775280] .
[27265.788424] ready
[27265.789297] sd 2:0:0:0: [sda] 58626287 512-byte logical blocks: (30.0 GB/28.0 GiB)
[27265.789773] sd 2:0:0:0: [sda] Write Protect is off
[27265.789776] sd 2:0:0:0: [sda] Mode Sense: 1f 00 10 08
[27265.790752] sd 2:0:0:0: [sda] Write cache: disabled, read cache: enabled, supports DPO and FUA
[27265.808120]  sda: sda1
[27265.836519] sd 2:0:0:0: [sda] Attached SCSI disk

パーティションテーブルを作成

gptで作成するので、gdiskを使います。

Windowsリカバリデータが入っていたので、一旦削除します。

sudo gdisk -l sda
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: not present


***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory.
***************************************************************

Disk sda: 58626287 sectors, 28.0 GiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 58626253
Partitions will be aligned on 2048-sector boundaries
Total free space is 4268 sectors (2.1 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048        58623999   28.0 GiB    0700  Microsoft basic data

d コマンドでパーティションを削除し、u コマンドで作成します。 詳しくはこちら

Hex code or GUID には EF00 を指定します。

Partition number (1-128, default 1):
First sector (34-58626253, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-58626253, default = 58626253) or {+-}size{KMGTP}: 256M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI System'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.

ファイルシステムを設定する

mkfs.vfat コマンドでfat32を設定します。

sudo mkfs.vfat -F32 /dev/sda1

grub2をインストールする。

以下のコマンドでインストールします。

sudo mount /dev/sda1 /mnt/disk1
sudo grub-install --target x86_64-efi --efi-directory /mnt/disk1 --boot-directory=/mnt/disk1/boot
Installing for x86_64-efi platform.
Installation finished. No error reported.
ls /mnt/disk1/
EFI/  boot/

UEFIの設定画面で起動順序を変更する

起動順序を変更し、SSDを一番最初に読むこむようにします。

grub2から本体のUbuntuを起動する

以下のコマンドで、本体のカーネルと初期RAMディスクを読み込むようにし、bootします。

set root=(hd1,gpt2)
linux /boot/vmlinuz-4.15.0-45-generic root=/dev/mmcblk0p2
initrd /boot/initrd.img-4.15.0-45-generic
boot

無事、本体のUbuntuが立ち上がりました。 触ってみてなんとなくイメージがつかめたので色々試してみます。

今回はここまで。

docker上で起動したfirefoxをホスト側で操作する

前回、簡単なX11アプリケーションをdocker上で起動、host側に表示することができましたが、もう少し踏み込んでブラウザを使えるようにします。

takapi86.hatenablog.com

結論から言うと、普通に閲覧できるようになりましたが、日本語入力ができなかったり、開いたページによっては途中でクラッシュしてしまったり課題が残っています。

環境

前回と同じで、ホスト・コンテナともに Ubuntu 18.04 です。

今回はdocker-composeを使います。

まずは簡単に動かしてみる

シンプルに以下を実行する

Dockerfile

FROM ubuntu:18.04

RUN apt-get update
RUN apt-get -y install firefox

ENTRYPOINT "firefox"

xhostの設定

xhost + local:root

docker-compose.yml

version: '3'
services:
  firefox:
    build: .
    volumes:
      - /tmp/.X11-unix/:/tmp/.X11-unix/
    environment:
      - DISPLAY=$DISPLAY

課題

上記でも動きますが、ホスト側と同じように動かためにはいくつか課題があります。

  • 日本語が文字化けしている(麻雀牌化する)
  • データが永続化されていない
  • 時刻がutc
  • 音が出ない
  • 日本語入力できない

それ以外にも、起動時にwarningなどのメッセージも出てきたり、たまにクラッシュしたりします。

課題を解決していく

warningが出ている

まずは、warningが出ているので対応していきます。

firefox_1  | (firefox:6): LIBDBUSMENU-GLIB-WARNING **: 08:26:42.616: Unable to get session bus: Failed to execute child process ?dbus-launch? (No such file or directory)

dbus-launch は、dbus-x11 というパッケージに入っているということなので、これをインストールして対応しました。 https://launchpad.net/ubuntu/bionic/+package/dbus-x11

firefox_1  | Gtk-Message: 11:37:45.029: Failed to load module "canberra-gtk-module"

これは、libcanberra-gtk-modulelibcanberra-gtk3-module をインストールして対応。

gtkGUI関連のライブラリとのこと https://developer.gnome.org/gtk3/stable/

日本語が文字化けしている(麻雀牌化する)

language-pack-ja と日本語フォントをインストールすれば解決

ついでに、localeの対応もします。

利用可能な全ロケールを確認

$ locale -a
C
C.UTF-8
POSIX
ja_JP.utf8

ja_JP.utf8 はフォントインストールしたときにはいったのかな? ロケール環境変数ja_JP.utf8 をセットするようにします。

LC_ALL=ja_JP.utf8

参考: https://lpi.or.jp/ex/102/ex_2901.shtml

データが永続化されていない

ホストのどっかに退避するだけです。 私は $HOME 以下と同期させるようにしました。

$HOME/.mozilla/:/home/user/.mozilla/
$HOME/ダウンロード/:/home/user/ダウンロード/
$HOME/.cache/:/home/user/.cache/

時刻がutcである

ホスト側(JST)と合わせます。

/etc/localtime:/etc/localtime

音が出ない

ホスト側では、pulseaudio というサウンドサーバが動いていて、ソケット経由で音声のやりとりができるというこいとでこの方法で対応します。

こちらの記事を参考にさせていただきました。 https://wafrelka.hatenablog.jp/entry/2016/04/16/233940

以下のファイルを共有し、

/run/user/[uid]/pulse/native
/home/user/.config/pulse/cookie

環境変数にもセットします。

PULSE_SERVER=/run/user/[uid]/pulse/native
PULSE_COOKIE=/home/user/.config/pulse/cookie

日本語入力できない

日本語の入力ができないというよりも、ホスト側のインプットメソッドの設定が反映されません。 インプットメソッドの仕組みまだよくわかっていので、まずはそこからかな。

たまにクラッシュする

未解決ですが、以下のようなメッセージがでるので引き続き確認してきます。

firefox_1  | [Parent 6, Gecko_IOThread] WARNING: pipe error (181): 接続が相手からリセットされました: file /build/firefox-DVGW0d/firefox-65.0.1+build2/ipc/chromium/src/chrome/common/ipc_channel_posix.cc, line 349
firefox_1  |
firefox_1  | ###!!! [Parent][MessageChannel] Error: (msgtype=0x1E0086,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv

まとめ

設定はこちらにまとめています。 github.com

こんな感じで試行錯誤しながら進めています。 日本語入力ができない件については、他のアプリケーションをdockerで動かす場合でも同じ問題が発生すると思うので、早めになんとかしていきたい気持ち。

参考

https://github.com/jessfraz/dockerfiles

docker上で動く猫と遊ぶ(X11のネットワーク周りの確認)

最近、Linuxをちゃんと学び直したいと思って、LPICをレベル1からやっています。 101は受かったので、次は102です。

その102の試験範囲に、X11周りの問題がでるので、この辺をdockerを使って色々試してみます。

今回は、X11のネットワーク周りの確認のため、onekoというX11クライアントをdockerで起動し、サーバ側で動かしてみるというところまでやりたいと思います。

インストールするX11アプリケーション

oneko 猫がマウスを追いかけてきます。 https://packages.ubuntu.com/ja/bionic/oneko

環境

  • 実機(Xサーバ)
cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.2 LTS"
  • dockerコンテナ(Xクライアント)

ubuntu:18.04 イメージ

socket経由で猫を飛ばす

Dockerfile

onekoX11アプリケーションを動作させるため x11-apps をインストールします。

FROM ubuntu:18.04

RUN apt-get update && apt-get install -y x11-apps
RUN apt-get install -y oneko
ENTRYPOINT /usr/games/oneko

docker側ではユーザがrootで実行されるので、xhostを指定してあげる必要があります。 (ホスト側と同じユーザで実行していれば以下の設定は不要)

xhost + local:root

dockerコマンド

docker run --rm -v /tmp/.X11-unix/:/tmp/.X11-unix/ -e DISPLAY=$DISPLAY -it oneko_oneko oneko

ピコっと猫が出てきました。マウスを追いかけてきます。 (そういえば、ジオシティーズ全盛期、HP上でこういうの動かせるようになってるページめちゃくちゃあったなぁ。)

f:id:takapi86:20190310222854p:plain

TCP経由で猫を飛ばす

  • ディスプレイマネージャーの設定で、TCPが許可されているか確認

私の環境はgdm3なので、

/etc/gdm3/custom.conf

[security]
DisallowTCP=false

があるか確認し、なければ追加します。

変更を反映させるために ディスプレイマネージャーをリスタートします。(デスクトップの再起動)

すると、以下のように6000をLISTENするようになっているはずなので、

sudo netstat -anp | grep 6000
tcp        0      0 0.0.0.0:6000            0.0.0.0:*               LISTEN      2563/Xorg
tcp6       0      0 :::6000                 :::*                    LISTEN      2563/Xorg

以下のコマンドを叩くと、猫が出てくるはずです。

docker run --rm --net host -e DISPLAY=$DISPLAY -it oneko_oneko oneko

本来のサーバ/クライアントの設定としては、$DISPLAY にXサーバを指定、xhost に許可したいXクライアントを指定していくらしいのですが、host, ipを調べて設定するのが、ちょっと面倒くさいというのがあるので、今回はこのやり方で対応しました。


Windows(vcxsrv)や、Mac(XQuartz)でもX11が使えるので、上手く使えば、重いIDEなどを分離させたいとき、複数環境使いたいときなどに便利かもしれないなという気持ちでした。

参考