4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ブラウザからワンクリックでサーバ上にdockerコンテナを立ち上げる

Last updated at Posted at 2022-12-14

この記事はニフクラ 等を提供している、富士通クラウドテクノロジーズ Advent Calendar 2022 の15日目の記事です。

前日は @earth429さんのSpotifyのNowPlayingを投稿しステータスに設定もしてくれるSlackbotを作ってみたでした。
弊社にはSlackに現在聞いている曲を共有するチャンネルがあるのですが、そのチャンネルでめちゃくちゃ活躍してくれそうだなと感じました。
AppleMusic版もほしいな、、

はじめに

本記事では、ブラウザから「コンテナ作成」ボタンを押すだけでサーバ上にDockerコンテナを作成する方法について記述します。

最低限の構成を紹介するので、必要に応じて増やしたり減らしたりしてみてください。
やってることは簡単なことの組み合わせだと思います。(方法2は少し難しいかも)

方法1と方法2を記述するので、好きな方を選んでください。
おすすめは方法2です。

ゴール

  • ブラウザ(chromeやfirefoxなど)から「コンテナ作成」のボタンを押すと、裏で動いているサーバ上にDockerコンテナが作成されること
  • ブラウザから作成したコンテナにアクセスできること(今回はApacheコンテナ)

方法1,2の違い

方法1

  • APIサーバからAPPサーバのDockerを操作する(docker -H)
  • docker -Hが公式から推奨されていない
  • 実装内容の理解は簡単かも
  • UIサーバ、APIサーバ、APPサーバで合計3台のサーバが必要

方法2

  • APPサーバ上でAPPサーバのDockerを操作する
  • DockerAPIを直接叩くので実装内容理解がちょっと大変かも
  • Docker公式非推奨の方法を避けることができる
  • (この記事ではAPIサーバを用意したが)APIサーバを省いてUIサーバとAPPサーバの2台で構成できる

構成図

image.png

環境

  • UIサーバ
    • CentOS7.4.1708
    • Apache/2.4.6
    • PHP7.4.30
  • APIサーバ
    • CentOS7.4.1708
    • Apache/2.4.6
    • Docker20.10.17
    • PHP7.4.30
  • APPサーバ
    • CentOS7.4.1708
    • Apache/2.4.6
    • Docker20.10.17

実装の流れ

方法1,2共通

  1. UIサーバ,APIサーバ,APPサーバを作成する
  2. UIサーバにApache、PHPをインストール
  3. APIサーバにApache、Docker、PHPをインストール
  4. APPサーバにApache、Dockerをインストール
  5. FWの設定

方法1
6. APIサーバからAPPサーバのDockerを操作できるように設定
7. UIサーバ上にHTML,PHPのファイルを配置
8. APIサーバ上にPHPのファイルを配置
9. APPサーバ上に使いたいコンテナイメージを入れる
10. 動作確認

方法2
6. APPサーバのDockerをDockerAPIで直接叩けるように設定
7. UIサーバ上にHTML,PHPのファイルを配置
8. APIサーバ上にPHPのファイルを配置
9. APPサーバ上にPHPのファイルを配置
10. APPサーバ上に使いたいコンテナイメージを入れる
11. 動作確認

以下、実装の流れに沿って解説していきます。

方法1,2共通

UIサーバ,APIサーバ,APPサーバを作成する

好きなサービス、もしくは自前でUIサーバ,APIサーバ,APPサーバを作成してください。
今回はCentOS7.4の想定で進めます。

UIサーバにApache、PHPをインストール

UIサーバにApache、PHPをインストールします。

yum -y install httpd

yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi,remi-php74 php php-mbstring php-xml

参考
CentOS7へPHP7.4をインストール

APIサーバにApache、Docker、PHPをインストール

APIサーバにApache、Docker(方法1のみ)、PHPをインストールします。

yum -y install httpd

## 方法1のみ
yum -y install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum -y install docker-ce

yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi,remi-php74 php php-mbstring php-xml

参考
Docker CEをCentOS 7にyumインストールする手順
CentOS7へPHP7.4をインストール

APPサーバにApache、Docker、PHPをインストール

APPサーバにApache(方法2のみ)、Docker、PHP(方法2のみ)をインストールします。

## 方法2のみ
yum -y install httpd

yum -y install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum -y install docker-ce

## 方法2のみ
yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi,remi-php74 php php-mbstring php-xml

参考
Docker CEをCentOS 7にyumインストールする手順

FWの設定

それぞれのサーバ間で通信できるように&UIサーバのコンテンツをブラウザから見られるようにFWのINルールを追加します。
UIサーバはコンテナ作成ボタンを配置するためのサーバなので、/var/www/html/配下がブラウザから見れる必要があります。

  • ブラウザ→UIサーバ...80番ポート(http用)
  • ブラウザ→APPサーバ...8080番ポート(作成したコンテナアクセス用)
  • UIサーバ→APIサーバ...80番ポート(http用)
  • APIサーバ→APPサーバ...2375番ポート(Docker用)※方法1の場合のみ
  • APIサーバ→APPサーバ...80番ポート(http用)※方法2の場合のみ

方法1

APIサーバからAPPサーバのDockerを操作できるように設定

APIサーバからAPPサーバのDockerを操作できるようにdocker -Hのオプションを使えるようにします。

警告
この方法はDocker公式サイトで非推奨とされています。使用する場合は注意してください。

APPサーバに/etc/docker/daemon.jsonを作成、追記します。

/etc/docker/daemon.json
{"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]}

APPサーバに/etc/systemd/system/docker.service.d/docker.confを作成、追記します。

/etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd                    

設定を変更したのでAPPサーバのDockerを再起動します。

systemctl restart docker

警告

-H オプションを使うと、Docker デーモンは指定した IP アドレスとポートをリッスンします(ポートを開きます)。標準では、unix:///var/run/docker.sock をリッスンし、ローカルの root ユーザのみ接続できます。これを 0.0.0.0:2375 や特定のホスト IP を指定することで、誰でもアクセス可能にできましたが、推奨されていません。理由は、デーモンが稼働しているホスト上の root アクセスを誰もが簡単に得られるためです。

参考
Docker デーモンの設定とトラブルシュート

UIサーバ上にHTML,PHPのファイルを配置

UIサーバ上にコンテナ作成用のボタンを配置します。
(最低限の機能実装なので、必要に応じて追記してください。)

UIサーバに/var/www/html/index.htmlを作成、追記

/var/www/html/index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>APIにpostリクエストを送信する</title>
    </head>
    <body>
        <form action="post.php" method="post">
            <button type="submit" name="create">作成</button><br>
        </form>
    </body>
</html>

ブラウザから見た画面↓
image.png

UIサーバに/var/www/html/post.phpを作成、追記します。

/var/www/html/post.php
<?php

$url = 'http://${APIサーバのIP}/api.php';

$data = array(
    'name' => 'test'
    'image' => 'httpd',
);

$context = array(
    'http' => array(
        'method'  => 'POST',
        'header'  => implode("\r\n", array('Content-Type: application/x-www-form-urlencoded',)),
        'content' => http_build_query($data),
    )   
);

$html = file_get_contents($url, false, stream_context_create($context));

echo $html . "<br>";
echo "コンテナを作成しました";

参考
PHPでPOST送信まとめ

APIサーバ上にPHPのファイルを配置

UIサーバで「作成」ボタンを押すと送信されるPOSTリクエストを処理するためのプログラムを作成、配置します。

APIサーバに/var/www/html/api.phpを作成、追記します。

/var/www/html/api.php
<?php

$cmd = "docker -H ${APPサーバのIP} run -d -p 8080:80 --name " . escapeshellarg($_POST['name']) . ' ' . escapeshellarg($_POST['image']) . ":latest";
echo exec($cmd) . "\n";

このプログラムが動くことでAPPサーバ上にコンテナが立ち上がります。(今回はApacheのコンテナ)

APPサーバ上に使いたいコンテナイメージを入れる

今回はApacheのコンテナを動かしたいので事前にhttpdのイメージを入れておきます。

docker pull httpd

これですべて準備が完了したはずです。

動作確認

ブラウザからUIサーバにアクセスします。

image.png

「作成」ボタンが表示されます。

そのボタンをクリックします。

image.png

コンテナが作成されます。

作成されたコンテナにアクセスしてみます。
APPサーバ上に作成されているのでAPPサーバの8080番ポートにブラウザからアクセスします。

image.png

Apacheが動いていることが確認できました。

一応APPサーバの裏側でもちゃんと動いているか確認します。

[root@app ~]# docker ps
CONTAINER ID   IMAGE          COMMAND              CREATED         STATUS         PORTS                                   NAMES
6387a999e61f   httpd:latest   "httpd-foreground"   6 minutes ago   Up 6 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   test

ちゃんと動いていることが確認できました。

方法2

APPサーバのDockerをDockerAPIで直接叩けるように設定

APPサーバのDockerをDockerAPIで直接叩けるように設定します。

APPサーバに/etc/docker/daemon.jsonを作成、追記します。

/etc/docker/daemon.json
{"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]}

APPサーバに/etc/systemd/system/docker.service.d/docker.confを作成、追記します。

/etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd                    

設定を変更したのでAPPサーバのDockerを再起動します。

systemctl restart docker

UIサーバ上にHTML,PHPのファイルを配置

UIサーバ上にコンテナ作成用のボタンを配置します。
(最低限の機能実装なので、必要に応じて追記してください。)

UIサーバに/var/www/html/index.htmlを作成、追記

/var/www/html/index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>APIにpostリクエストを送信する</title>
    </head>
    <body>
        <form action="post.php" method="post">
            <button type="submit" name="create">作成</button><br>
        </form>
    </body>
</html>

ブラウザから見た画面↓
image.png

UIサーバに/var/www/html/post.phpを作成、追記します。

/var/www/html/post.php
<?php

$url = 'http://${APIサーバのIP}/api_post.php';

$data = array(
    'name' => 'test',
    'image' => 'httpd',
);

$context = array(
    'http' => array(
        'method'  => 'POST',
        'header'  => implode("\r\n", array('Content-Type: application/x-www-form-urlencoded',)),
        'content' => http_build_query($data),
    )   
);

$html = file_get_contents($url, false, stream_context_create($context));

echo $html . "<br>";
echo "コンテナを作成しました";

参考
PHPでPOST送信まとめ

APIサーバ上にPHPのファイルを配置

APIサーバ上にUIサーバから来たPOSTをAPPサーバにPOSTするPHPファイルを配置します。
(APIサーバを飛ばして直接UIサーバからAPPサーバにPOSTを送りつけても大丈夫です。)

APIサーバに/var/www/html/api_post.phpを作成、追記します。

/var/www/html/api_post.php
<?php

$url = 'http://${APPサーバのIP}/run.php';

$data = array(
    'name' => "{$_POST['name']}",
    'image' => "{$_POST['image']}",
);

$context = array(
    'http' => array(
        'method'  => 'POST',
        'header'  => implode("\r\n", array('Content-Type: application/x-www-form-urlencoded',)),
        'content' => http_build_query($data),
    )   
);

$html = file_get_contents($url, false, stream_context_create($context));

echo $html;

参考
PHPでPOST送信まとめ

APPサーバ上にPHPのファイルを配置

APPサーバ上にAPIサーバから来たPOSTを受け取り、Dockerコンテナを起動するためのPHPファイルを配置します。

APPサーバに/var/www/html/run.phpを作成、追記します。

/var/www/html/run.php
<?php

$data = array(
    'name' => $_POST['name'],
    'image' => $_POST['image'],
);

// create
$url = sprintf('http://127.0.0.1:2375/v1.41/containers/create?name=%s',
    urlencode($data['name'])
);

$context = array(
    'http' => array(
        'method'  => 'POST',
        'header'  => implode("\r\n", array('Content-Type: application/json',)),
        'content' => json_encode(array(
            'Image' => $data['image'],
            'HostConfig' => array(
                'PortBindings' => array(
                    '80/tcp' => array(
                        array('HostPort' => '10080')
                    )
                )
            )
        ))
    )   
);

$res = file_get_contents($url, false, stream_context_create($context));

echo $res;

// start
$url = sprintf('http://127.0.0.1:2375/v1.41/containers/%s/start',
    urlencode($data['name'])
);

$context = array(
    'http' => array(
        'method'  => 'POST'
    )   
);

$res = file_get_contents($url, false, stream_context_create($context));

echo $res;

このプログラムが動くことでDockerコンテナが起動します。

少し説明します。
DockerはDockerコマンドを叩く以外にも、DockerAPIで叩くこともできます。(詳細は参考サイトを読んで下さい。)
// createの部分ではコンテナの作成コマンドを叩いています。いわゆるdocker createですね。
// startの部分ではコンテナ起動のコマンドを叩いています。いわゆるdocker startです。

わざわざDockerコマンドではなく、DockerAPIで叩いているのは、Dockerコマンドを直接叩こうとするとroot権限が必要になるため、スクリプトでは叩けません。
なのでDockerAPIで直接叩いています。

参考
Docker Engine API について
Docker Engine SDK および Docker API の利用例

APPサーバ上に使いたいコンテナイメージを入れる

今回はApacheのコンテナを動かしたいので事前にhttpdのイメージを入れておきます。

docker pull httpd

これですべて準備が完了したはずです。

動作確認

ブラウザからUIサーバにアクセスします。

image.png

「作成」ボタンが表示されます。

そのボタンをクリックします。

image.png

コンテナが作成されます。

作成されたコンテナにアクセスしてみます。
APPサーバ上に作成されているのでAPPサーバの8080番ポートにブラウザからアクセスします。

image.png

Apacheが動いていることが確認できました。

一応APPサーバの裏側でもちゃんと動いているか確認します。

[root@app html]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS                                   NAMES
cd441a666d14   httpd     "httpd-foreground"   6 seconds ago   Up 5 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   test

ちゃんと動いていることが確認できました。

まとめ

  • ブラウザ(chromeやfirefoxなど)から「コンテナ作成」のボタンを押すと、裏で動いているサーバ上にDockerコンテナが作成された
  • ブラウザから作成したコンテナにアクセスできた

おわりに

この記事は富士通クラウドテクノロジーズ Advent Calendar 2022 の15日目の記事でした。

明日は@ktakaakiさんのITエンジニアがレザークラフトを真面目にやってみたです。
洋服とか靴とか財布とか、革製品がマイブームなのでとても楽しみです!

この記事は必要最低限の動作をするシステムですので、必要に応じて改良してください。
誰かの役に立てば幸いです。
最後まで読んでいただきありがとうございました。

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?