LoginSignup
3
3

More than 3 years have passed since last update.

【Go】コンテナを理解するためにコンテナを自分で”造る”【初心者】

Last updated at Posted at 2020-06-02

コンテナを理解するためにコンテナを自分で"造る"

今回はこちらを参考にして自作コンテナを作ってみる。

コンテナとは

詳しくは他の方の説明を受けてください。

Goでコンテナを"造る"

環境

今回はVMwareUbuntuを稼働させ、VM上で造りました。

Ubuntu 20.04 LTS 64-bit

go version go1.13.8 linux/amd64

まずはコンテナのルートディレクトリとなるFile Systemを作る

/home/rootfsディレクトリ下に今回のルートディレクトリとなるFile System(fs)を作成します。

/home/rootfs/
  ├── bin
  ├── lib
  ├── lib32
  ├── lib64
  ├── proc   \\空のディレクトリ
  └── sbin

bin,lib,lib32,lib64,sbinディレクトリは/usrディレクトリ下と同じものをコピーしました。

procディレクトリは空の状態で作成しておきます。

※今回はただコンテナとして動くことだけを目的としているので最小のfsにしています。

コンテナを稼働させるsrc【Go】

src次のようにしました。

package main

import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    switch os.Args[1] {
    case "run":
        run()
    case "child":
        child()
    default:
        panic("what??")
    }
}

func run() {
    cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID,
    }

    must(cmd.Run())
}

func child() {
    fmt.Printf("running %v as PID %d\n", os.Args[2:], os.Getpid())

    cmd := exec.Command(os.Args[2], os.Args[3:]...)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    must(syscall.Chroot("/home/rootfs"))
    must(os.Chdir("/"))
    must(syscall.Mount("proc", "proc", "proc", 0, ""))
    must(cmd.Run())
}

func must(err error) {
    if err != nil {
        panic(err)
    }
}

実際にコンテナを起動してみる

まずはホストのfsProcessの確認

Terminalでホストのfsを確認しましょう。

~$ cd /
~$ ls
bin    dev   lib    libx32      mnt   root  snap      sys  var
boot   etc   lib32  lost+found  opt   run   srv       tmp
cdrom  home  lib64  media       proc  sbin  swapfile  usr

次に、ホストのProcessを確認

~$ ps
    PID TTY          TIME CMD
   1927 pts/0    00:00:00 bash
   2950 pts/0    00:00:00 ps

PID(Process ID)が大きい値であるのが確認できます。

コンテナを起動

満を持してコンテナを起動しましょう。

先ほどのsrcがあるディレクトリに移動し、Terminalで次のようにコマンドを入力します。

~:/home/{username}/{directoryname}$ sudo go run main.go run /bin/bash
running [/bin/bash] as PID 1
bash-5.0# 

おめでとうございます!

コンテナが起動しました!

コンテナがコンテナであるか確認する

ホストの時と同じようにfsProcessを確認してみましょう。

bash-5.0# cd /
bash-5.0# ls
bin  lib  lib32  lib64  proc  sbin

コンテナ内で/ディレクトリに移動してもホストの/home/rootfsディレクトリに移動しますね。

bash-5.0# ps
    PID TTY          TIME CMD
      1 ?        00:00:00 exe
      6 ?        00:00:00 bash
      8 ?        00:00:00 ps

PIDちゃんと小さい値です。

ついでにhistoryも確認しておきましょう。

bash-5.0# history 
    1  cd /
    2  ls
    3  ps
    4  history 

historyもコンテナ内の記録しか表示されません。

最後にコンテナを停止するには

コンテナ内でexitと入力すればOK

bash-5.0# exit
~:/home/{username}/{directoryname}$
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3