LoginSignup
50
38

More than 3 years have passed since last update.

Dockerコンテナ内のUbuntuではsystemctlは使えない

Last updated at Posted at 2020-10-15

はじめに

システムやアプリケーションを作るにあたり、Dockerコンテナ上で構築ができれば、開発やメンテの効率に繋がるかと思い色々と試しみたので、その基礎的なことをまとめる。
 ※一番ハマったところをタイトルにした。

前提条件

【ホストOS】
 ・Ubuntu20.04 LTS(GCP上)

【ソフト・イメージ Version】
 ・docker19.03.13
 ・コンテナイメージのOS Ubuntu20.04 LTS

やりたい事

1.dockerのインストールと設定
2.dockerにコンテナ作成
3.コンテナに入ってApache起動
4.イメージファイルを改造して再度イメージ化

1.dockerのインストールと設定

Docker社のリポジトリからインストールする場合は、以下の手順となる。
※バージョン14.04以降、aptコマンドが推奨となっているためapt-getは使用しない。

Dockerがインストールされていない事を確認

$ sudo dpkg -l docker

dpkg-query: no packages found matching docker と表示されればインストールされていない。

パッケージ管理ツールのアップデート

$ sudo apt update

Dockerインストールに必要なソフトインストール

$ sudo apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

Docker公式のGPG公開鍵を追加

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

ちゃんと公開鍵が追加されたか確認

$ sudo apt-key fingerprint

Qiita-no010_img04.jpg

リポジトリの追加

リポジトリにdockerがない事を確認。
 ※以下のコマンドを実行しても、何も表示されないはず。

$ cat /etc/apt/sources.list | grep docker

リポジトリの設定

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

リポジトリが追加された事を確認

$ cat /etc/apt/sources.list | grep docker
deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
# deb-src [arch=amd64] https://download.docker.com/linux/ubuntu focal stable

使用可能なバージョンを確認

$ apt-cache madison docker-ce
 docker-ce | 5:19.03.13~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:19.03.12~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:19.03.11~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:19.03.10~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:19.03.9~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages

dockerのインストール

リポジトリが追加されたため再度updateしてからinstallを実行

$ sudo apt update
$ sudo apt install docker-ce

インストールしたdockerのバージョンを確認

$ sudo docker version
Client: Docker Engine - Community
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:02:52 2020
 OS/Arch:           linux/amd64
 Experimental:      false

デーモンが起動されているか確認

$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2020-09-30 00:22:29 UTC; 30min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 25020 (dockerd)
      Tasks: 9
     Memory: 36.8M
     CGroup: /system.slice/docker.service

dockerの動作確認

Hello world サンプルdockerイメージを取得して実行。

$ sudo docker container run hello-world

現在のイメージとコンテナの一覧を確認

# イメージの一覧表示
$ sudo docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB

# コンテナの一覧表示(停止中を含む)
$ sudo docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS   
            NAMES
e8a73ecd0c16        hello-world         "/hello"            5 minutes ago       Exited (0) 5 minutes ago           
            condescending_diffie

# 起動中のコンテナ表示
$ sudo docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS          
     NAMES

※hello-worldのコンテナはメッセージ出力後にコンテナを停止してしまうので起動中になっていない。

動作確認ができたので一旦コンテナとイメージの削除。

$ sudo docker container rm [コンテナID]
$ sudo docker image rm [イメージID]

dockerの設定

自動起動の設定

$ sudo systemctl unmask docker.service
$ sudo systemctl enable docker
$ sudo systemctl is-enabled docker

sudoなしでdockerコマンド実行するためdockerグループに追加。

# まずは[docker]グループの確認。 ※グループがない場合は自分で作成する必要がある。
$ cat /etc/group | grep docker
docker:x:998:

# [docker]グループにユーザーを追加。
$ sudo usermod -aG docker [ユーザー名]

Ubuntuの再起動後、以下の様にsudoなしでコマンドを実行できれば設定変更はできている。
※再起動はGCPから実行。(GCP上でVMインスタンスを作成しているため)

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

2.dockerにコンテナ作成

コンテナはdockerイメージを使って構築するので、まずはdockerイメージを取得する。
dockerのサイトには既にたくさんのイメージが公開されているので、検索コマンドで目的のイメージを探してきて、イメージを取得する

取得するイメージの確認

$ docker search 【任意なキーワード】

イメージの取得

# docker image pull [OPTIONS] NAME[:TAG|@DIGEST]
$ docker image pull  ubuntu:20.04

20.04: Pulling from library/ubuntu
d72e567cc804: Pull complete 
0f3630e5ff08: Pull complete 
b6a83d81d1f4: Pull complete 
Digest: sha256:bc2f7250f69267c9c6b66d7b6a81a54d3878bb85f1ebb5f951c896d13e6ba537
Status: Downloaded newer image for ubuntu:20.04
docker.io/library/ubuntu:20.04

※今回はホストOSがUbuntu20.04の上に、Ubuntu20.04のコンテナを作成。

イメージからコンテナ作成

$ docker container run -it -d --name test-ubuntu20-4 ubuntu:20.04

# ポート番号を紐づけたい時
# docker container run -it -d -p 8080(Ubuntu側のポート):5000(コンテナ側のポート) --name webgis-server ubuntu:20.04

※1).イメージがローカルホストに存在しない場合、docker container run実行時にそのイメージをリポジトリから自動的にpullして、コンテナを作成してくれる。
※2).[オプション]コマンドがない場合、コンテナは起動後すぐに終了してしまう。

起動しているコンテナを確認

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS          
     NAMES
19b7ac7c40ad        ubuntu:20.04        "/bin/bash"         8 seconds ago       Up 7 seconds                       
     test-ubuntu20-4

3.コンテナに入ってApache起動

先程作成したコンテナ(test-ubuntu20-4)に入る

$ docker attach test-ubuntu20-4

※一度 exit で出るとコンテナが停止されるため、再度入る時には docker container start [コンテナ名] で起動させてから。

パッケージ管理ツールのアップデート。

# apt update

Apacheのインストール

# apt install -y apache2

※初めて何かパッケージをインストールすると、途中でエリアやタイムゾーンを聞かれるため、それぞれ以下の様に設定。
  ・Geographic area:6(Asia)
  ・Time Zone:79(Tokyo)

Apacheの起動状態を確認。

# systemctl status apache2
bash: systemctl: command not found

上記の様なメッセージが表示されてオペレートできないため、systemctlを使える様にパッケージのインストール 。(単純な起動などは service apache2 ~~~~のコマンドでできる。)

# apt install -y systemd

再度Apacheの起動状態を確認。

# systemctl status apache2
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

PID1に問題がありそうとのことなので確認してみる。

# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.5  0.1   4240  3384 pts/0    Ss   16:40   0:00 /bin/bash
root           8  0.0  0.1   5888  2912 pts/0    R+   16:40   0:00 ps aux 


実は docker container run -it -d --name ubuntu:20.04コマンドでコンテナを作成すると、コンテナ内Ubuntuの[PID:1]のCOMMANDが/sbin/bash となってしまう。
これだと、systemctl のコマンドが使えない様子。

※試しに最初のコンテナ作成時に、以下のコマンドで初期プロセスを /sbin/init に指定してみたが、イメージに /sbin/init が存在しないと言われる。

# テスト実行のため、今回の一連の作業としては実行不要。
$ docker container run -it -d --privileged --name webgis-server ubuntu:20.04 /sbin/init

docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process c
aused "exec: \"/sbin/init\": stat /sbin/init: no such file or directory": unknown.

/sbin/init が存在する Ubuntuをイメージ化すればできるかも!

4.イメージファイルを改造して再度イメージ化

/sbin/init/usr/lib/systemd/system/ へのシンボリックリンクとして作成。

# ln -s  /usr/lib/systemd/system/ /sbin/init

元のイメージに Apache2とSystemdのインストール 、/sbin/initの作成 をしたコンテナになっているので、一旦コンテナから出て停止したコンテナからイメージを作る。

$ docker commit test-ubuntu20-4 test-ubuntu20-4:add-init
sha256:5f25a8ff7149b22665aeb4d076919ba06d7e5c3f06c77834e60c6a7e042e6bf2

# イメージの一覧を確認
$ $ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
test-ubuntu20-4     add-init            91fffb874bf9        About a minute ago   202MB
ubuntu              20.04               9140108b62dc        2 weeks ago          72.9MB
hello-world         latest              bf756fb1ae65        9 months ago         13.3kB

イメージファイルから再度コンテナ作成

先程作成したイメージからコンテナ作成

$ docker container run -it -d --privileged --name test-ubuntu20-4-2 test-ubuntu2
0-4:add-init /sbin/init

af59767d9b17c60fcb5284ec3669bc61edb5f4a7e5a019b5c572997553d43e9f
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process c
aused "exec: \"/sbin/init\": permission denied": unknown.


今度はアクセス権がないとか言われ、結局[PID1 = /sblin/init]で起動させることは難しそう。
色々と調べてみたが、dockerコンテナ内ではプロセス管理ツールとしてsystemdは基本的に使えない。
(無理矢理やればできない事もないかもしれないが、そこまでするメリットもなさそう。)

 ・参考サイト1
 ・参考サイト2

まとめ

まずはdockerのインストールやコンテナの作成手順を簡単にまとめてみたが、VMとコンテナでは動作に使われるカーネルが異なるため、同じ様にプロセス管理ツールは使えない。
コンテナ内でサービスを作る場合、[PID1=init] が前提でdaemon化するプログラムは動作しない事を理解しておく。
dockerでプロセス管理を行いた場合、Supervisor というのが一般的らしい。

50
38
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
50
38