20201120のdockerに関する記事は14件です。

MacのDockerでUbuntu+ROSを動かす

自動運転車やロボットを動かすならROSだよね。ということで。
まずはMacでROSを動かしてみたいと思います。

DockerでUbuntuを動かす

参考:https://qiita.com/yasuoka_dev/items/073f7e8c7dba75993323

$ docker pull ubuntu:18.04

ユーザを作って、sudoできるようにしておく。

UbuntuにROSを入れる

参考:http://www1.meijo-u.ac.jp/~kohara/cms/technicalreport/ubuntu18-04_ros_install

aptへのROSのダウンロード先の登録

$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

sudoがない。。

$ apt-get update
$ apt-get install vim
$ apt-get install sudo

lsb_releaseがない。。
しかもこの状態でapt-get installしようとすると下記のファイルにゴミが残っているようでエラーに。。

E: Malformed entry 1 in list file /etc/apt/sources.list.d/ros-latest.list (Component)
E: The list of sources could not be read.
E: Malformed entry 1 in list file /etc/apt/sources.list.d/ros-latest.list (Component)
E: The list of sources could not be read.

ファイルを消してあげる。
しかもlsb_releaseでなく、lsb-releaseに変わっている。。罠が多すぎ。

$ rm /etc/apt/sources.list.d/ros-latest.list
$ sudo apt-get install lsb-release

最初から、sudo入れて、lsb-release入れて、その後にやろう。

ダウンロードのための公開鍵の取得

$ sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

gnupgがない。

$ sudo apt-get install gnupg

できたっぽい。

ROSのインストール

$sudo apt update
$sudo apt install ros-melodic-desktop-full

すごい数のパッケージ。1416パッケージ。
途中でなぜか都市の選択が。6:Asia>79:Tokyo を選択。
完了。

あと、rosdepのインストールは別途手動で必要なようなので、下記で入れる。

apt install python-rosdep

catkin_ws まで作成。
試しにパッケージを入れてみる。

$ sudo apt-get install -y ros-melodic-joystick-drivers

ros-tutorialsパッケージもいいかも。

日本語のチュートリアルドキュメントもあった。
https://github.com/tork-a/tork_moveit_tutorial/releases/tag/0.0.10

DockerだとGUIがないので、ブラウザから立ち上げるタイプもあった。
https://qiita.com/karaage0703/items/957bdc7b4dabfc6639da

$ docker run -p 6080:80 --shm-size=512m tiryoh/ros-desktop-vnc:melodic

コマンド一発。簡単すぎる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Dockerの概要)プログラマのためのDocker教科書のまとめ読む.2

※一度Zennに投稿したものです。次からこちらに投稿予定のため移行しました。

内容:docker概要〜イメージ、コンテナ操作

Dockerの基礎知識

Dockerとは

アプリケーション実行に必要な環境を1つのイメージにまとめ、さまざまな環境でアプリケーション実行環境を構築,運用するためのプラットフォーム。オープンソース。内部でコンテナ技術を使っている。
コンテナ技術とは、ホストOS上で論理的な区画を作り、個別のサーバーのように使うことができるようにしたもの。

Dockerではインフラ環境をコンテナとして扱う。

プログラマが作成した共通のDockerイメージを使うことで、開発からテスト/本番まですべて同じ実行環境で立ち上げることができるため、テスト環境や本番でなぜか動かないなどのトラブルがなくなる。

Docker3つの機能

  1. Dockerイメージを作る(Build)
  2. Dockerイメージを共有(Ship)
  3. Dockerコンテナを動かす機能(Run)

Dockerイメージを作る

Dockerはアプリケーション実行に必要になるプログラム本体/ライブラリ/ミドルウェアやOSの設定などを1つにまとめてDockerイメージをつくる。このイメージはコンテナの雛形になる。
1つのイメージで1つのアプリケーションをコンテナに入れる。

複数のコンテナを組み合わせてサービスを構築するのを推奨している。
docker-compose up -dなどでコンテナを立ち上げたとき、大体2つ以上コンテナの表示が出ていた理由。

DockerイメージはDockerコマンドを使って手動で作成もできるが、Dockerfileという設定ファイルを作成して管理することが継続的に運用する上で望ましい。

すでにあるイメージに別のイメージを重ねて、新しいイメージを作成できる。構成に差分があった部分を差分(イメージレイヤー)として管理する。

サイズが大きくなりやすいので、効率良くイメージを作成することが必要になってくる。

Dockerイメージを共有する

DockerイメージはDockerレジストリで共有できる。公式のDocker Hubがある。
Node.jsやUbuntuなどの公式イメージも置いてあり、ダウンロード可能。
個人でもアップロードできる。
ファイル名には命名規則がある(後述)

Dockerコンテナを動かす機能

コンテナの起動/停止/破棄を行うことができる。
他の仮想化技術ではOSから起動するので時間がかかるが、Dockerはすでに起動しているOSの上でプロセスを実行するので早い。

Dockerを構成する5つのコンポーネント

よく目にする機能はDockerEngineがほとんど。
- Docker Engine
- コア部分
- イメージ生成、コンテナ起動、Dockerコマンド実行も
- Docker Registry
- イメージ公開/共有
- 公式Docker HubもこのDocker Registryを使っている
- Docker Compose
- 複数コンテナ一元管理
- 複数のコンテナ構成情報をコードで定義し、コンテナ群を一元管理するツール
- Docker Machine
- Docker実行環境構築
- ローカルのVirtualBoxやクラウド環境のAWS EC2などにDocker実行環境をコマンドで自動生成するためのツール
- Dockerコンテナを動かすための機能
- Docker Swarm
- クラスタ管理
- 複数のDockerホストをクラスタ化するためのツール、集団を作るみたいな
- Kubernetes利用できる

AWSの、「Amazon EC2 Container Service」ではDocker実行環境のマネージドサービスを行っている。

Dockerが動く仕組み

Dockerはnamespaceでホスト上でコンテナを仮想的に隔離している。
namespaceでオブジェクトが衝突する可能性を減らす。sassで使ってる意味と同じ。

Linuxカーネルのnamespace機能は、Linuxオブジェクトに名前をつけることで6つの独立した環境を構築できる。
その6つは詳しく知らなくて良いけど、ファイル使うためにマウントさせたり、ユーザID作ったり、ネットワークの設定もろもろコンテナごとに独立して割り当ててくれるんだな。ということは理解しておいた方がよい。

リソース管理の仕組み(cgroups)

アプリは10%、デーモンは20% CPUの機能を使っていいよ 設定ができる。

cgroupsという機能でグループごとにCPUやメモリのリソースを振り分ける。
その制限をかけられた親の子も制限を受けるので、子が親の制限を超える設定を行っても制限がかかるしくみになっている。

ネットワークの構成

LinuxにDockerをインストールすると、サーバの物理NICがdocker0という仮想ブリッジネットワークに接続される。
172.17.0.0/16のサブネットマスクをもつプライベートIPアドレスが与えられる。
コンテナ内のeth0は、仮想NICがペアで割り当てられる。仮想NICはコンテナからみるとeth0として見える。
NICとは、ネットワークカード。LANケーブル刺すところ。eth0とは、NICのデバイス名のこと。

Dockerコンテナと外部ネットワークを通信するには、docker0と物理NICでパケットを転送するしくみが必要になる。それをNAPTの機能で接続する。

コンテナ起動時にコンテナ内で使用するWebサーバの80番ポートをホストOSの8080番ポートに転送するように設定する。
外部から8080ポートにアクセスすると、コンテナ内80番ポートに繋がる。

http://localhost:8080 → コンテナ内の80番ポートに

NAPT=IPマスカレード≠アドレス変換 1つのIPアドレスを複数のPCで共有する。

Dockerをインストールして使う

Mac,Windows対応してる方をインストールする。
公式ページ

Dockerの情報を確認する

バージョンの確認

$ docker version

実行環境の確認

$ docker system info

ディスク利用状況の確認

$ docker system df

Webサーバを立ち上げてみる

Nginxのイメージをダウンロードする

Docker HubにあるNginx公式イメージ

$ docker pull nginx

イメージがダウンロードできているかを確認

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              hogehoge            9 days ago          133MB
ubuntu              latest              hogehoge            12 months ago       64.2MB

REPOSITORYにnginxがあるのでダウンロードできている。

コンテナを作成して(サーバを)起動する

webserverという名前のコンテナを作る。
-pオプションでブラウザからHTTP(80番ポート)でアクセスを許可する。portのpかしら
nginxのイメージを使ってwebserverという名前のコンテナを生成する。

$ docker container run --name webserver -d -p 80:80 nginx
<ここにコンテナID(英数字のわりと長めの文字が表示される)>

http://localhost:80/
にアクセスして、Welcome to nginx!の表示が出たらサーバの起動が成功した。

起動しているコンテナの状態を確認する

$ docker container ps
CONTAINER ID      IMAGE   ~略~ PORTS                NAMES
0854671a9400      nginx   ~略~ 0.0.0.0:80->80/tcp   webserver

POSTSを見るとポートの設定が 80->80 にできていることが確認できた。

コンテナを停止する

$ docker stop webserver

コンテナを再び起動する

停止しているコンテナを起動する場合。

$ docker start webserver

イメージの操作

イメージをダウンロード

$ docker image pull [オプション] イメージ名[:タグ名]

バージョン違いなどで指定したい場合はタグ名をつける。
タグ名を省略すると最新版(latest)がダウンロードされる。

DockerHubのページにインストール用のコマンドを記述してくれているので、それを使うとよきかも。

イメージ一覧を表示

$ docker image ls [オプション] [レポジトリ名]
オプション 説明
-a すべてのイメージを表示
--digests ダイジェストを表示
-no-trunc 結果を全て表示
-q DockerイメージIDのみ表示

--digestsはダイジェストが付与されているイメージを表示したいときに使う。Dockerレジストリへアップロードしたらダイジェストが付与される。

イメージの詳細を確認

$ docker image inspect [イメージ名]

イメージID,作成日,Dockerバージョン,CPUのアーキテクチャを取得できる。
結果はJSON形式で表示される。

イメージにタグ(別名)を設定

目印になるためにタグをつけることができるが、イメージがコピーされるわけじゃないので注意すること。(imageIDは同じ)
命名規則は、以下の規則でユーザ名をつけること。

<dockerHubユーザ名> / イメージ名:[タグ名]

Docker Hubへアップロードするときもこの命名規則は守らないといけないみたい。

$ docker image tag nginx hazyuz/webserver:1.0

$ docker image ls
REPOSITORY          TAG          IMAGE ID            CREATED             SIZE
hazyuz/webserver    1.0          c39a868aad00        9 days ago          133MB
nginx               latest       c39a868aad00        9 days ago          133MB

誰が作って、どのイメージなのかがすぐにわかる。
→hazyuzが作った、Webサーバ用のイメージ

イメージを削除する

$ docker image rm [オプション] イメージ名かイメージID

$ docker image rm nginx

-fオプションをつけることでイメージを強制的に削除できる。

$ docker image rm -f nginx

未使用のイメージを削除する

$ docker image prune [オプション]

-aオプションで使用していないイメージをすべて削除
-fオプションでイメージを強制的に削除

使っていないDockerイメージは容量を圧迫するので、定期的に削除するとよい

コンテナの操作

イメージがあると、コンテナを生成できる。
コンテナはイメージの スナップショット のようなもの。

コンテナを生成する

$ docker container create

イメージからコンテナを生成する。
イメージの実態は、Dockerでサーバ機能を動かすために必要なディレクトリやファイル群のこと。
以下のコマンドで、コンテナを生成する。
(そのファイル群のスナップショットを撮る。)

コンテナを起動する準備が整った状態になった。起動はまだしていない。

コンテナを生成/起動する

イメージからコンテナを生成し、コンテナ上で任意のプロセスを起動できる。
Nginxなどのサーバープロセスをバックグラウンドで常時実行したり、ポート番号などのネットワークを設定すると外部からコンテナプロセスへアクセスできる。

バックグラウンドでサーバ機能を持たせる

-dオプションをつけると、バックグラウンドでコンテナを起動できる。
バックグラウンドで実行することをデタッチモードと言う。

バックグラウンドでネットワークの設定をして起動する。

$ docker container run --name webserver -d -p 8080:80 nginx

ホストへのアクセス http://localhost:8080 が、コンテナにの80番ポートへ転送される。

コンテナ内に入りでシェル(/bin/bash)を実行する。

$ docker container run -it --name "test2" centos /bin/bash
[root@aaaaaaa /]#

終了する時は exit入力。

稼働しているコンテナに入る場合はdocker container attach コンテナ識別子を使う。

その他

他にもオプションで、CPUやメモリを指定してコンテナを生成したり、ホストOSとコンテナ内のディレクトリを共有する設定もできる。環境変数なども。必要なときに都度調べる。

コンテナ一覧を確認

オプションなしで、稼働しているコンテナ一覧を表示

$ docker container ls [オプション]

-aオプションで停止しているコンテナ一覧を表示

$ docker container ls -a

コンテナの稼働状況を確認

CPUやメモリ状況を見たい時など

$ docker container stats [コンテナ識別子]

コンテナを起動

停止中のコンテナを起動する。

$ docker container start [コンテナ識別子]

コンテナを停止

起動しているコンテナを停止する。
コンテナを削除するときはコンテナを停止しておく必要がある。

$ docker container stop [コンテナ識別子]

コンテナを再起動するとき。

$ docker container restart [コンテナ識別子]

コンテナを削除

$ docker container rm [コンテナ識別子]

-fで強制的に削除

$ docker container rm -f [コンテナ識別子]

※ネットワークと稼働中コンテナの操作は次に

まとめ

Dockerの内部ネットワークの構成は仮想NICがコンテナに割り振られて、それをホストOSと繋げる設定をすることでコンテナのサーバへのアクセスが可能になる。
Dockerイメージというのは、ディレクトリやファイル群が集まっていてパッケージされたもので、重なったレイヤーのようになっている。
コンテナとは、イメージのスナップショット。

イメージとコンテナの関係

コンテナはイメージのスナップショットのようなもの。

これをgitHubで例えてみると、それぞれの機能を作ったブランチがレイヤーでそれをマージしたmasterブランチがイメージ。
masterブランチをローカル環境へpullすることが、コンテナを生成するということ。
新しいブランチをmasterから切る時(コンテナを削除して再び生成するときは)、前のイメージとは違った新しい内容(レイヤーが追加されているかもしれない)になっている場合がある。

なので、コンテナはスナップショットと本では表現していたのかな。違うかも。

?コンテナのコマンド部分なんですが、オプションが多くてよく使うものとあまり使わないものの区別がつかったので、使ったことがあるオプションしか記述してません。

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Dockerの概要)プログラマのためのDocker教科書読む.2

※一度Zennに投稿したものです。次からこちらに投稿予定のため移行しました。

内容:docker概要〜イメージ、コンテナ操作

Dockerの基礎知識

Dockerとは

アプリケーション実行に必要な環境を1つのイメージにまとめ、さまざまな環境でアプリケーション実行環境を構築,運用するためのプラットフォーム。オープンソース。内部でコンテナ技術を使っている。
コンテナ技術とは、ホストOS上で論理的な区画を作り、個別のサーバーのように使うことができるようにしたもの。

Dockerではインフラ環境をコンテナとして扱う。

プログラマが作成した共通のDockerイメージを使うことで、開発からテスト/本番まですべて同じ実行環境で立ち上げることができるため、テスト環境や本番でなぜか動かないなどのトラブルがなくなる。

Docker3つの機能

  1. Dockerイメージを作る(Build)
  2. Dockerイメージを共有(Ship)
  3. Dockerコンテナを動かす機能(Run)

Dockerイメージを作る

Dockerはアプリケーション実行に必要になるプログラム本体/ライブラリ/ミドルウェアやOSの設定などを1つにまとめてDockerイメージをつくる。このイメージはコンテナの雛形になる。
1つのイメージで1つのアプリケーションをコンテナに入れる。

複数のコンテナを組み合わせてサービスを構築するのを推奨している。
docker-compose up -dなどでコンテナを立ち上げたとき、大体2つ以上コンテナの表示が出ていた理由。

DockerイメージはDockerコマンドを使って手動で作成もできるが、Dockerfileという設定ファイルを作成して管理することが継続的に運用する上で望ましい。

すでにあるイメージに別のイメージを重ねて、新しいイメージを作成できる。構成に差分があった部分を差分(イメージレイヤー)として管理する。

サイズが大きくなりやすいので、効率良くイメージを作成することが必要になってくる。

Dockerイメージを共有する

DockerイメージはDockerレジストリで共有できる。公式のDocker Hubがある。
Node.jsやUbuntuなどの公式イメージも置いてあり、ダウンロード可能。
個人でもアップロードできる。
ファイル名には命名規則がある(後述)

Dockerコンテナを動かす機能

コンテナの起動/停止/破棄を行うことができる。
他の仮想化技術ではOSから起動するので時間がかかるが、Dockerはすでに起動しているOSの上でプロセスを実行するので早い。

Dockerを構成する5つのコンポーネント

よく目にする機能はDockerEngineがほとんど。
- Docker Engine
- コア部分
- イメージ生成、コンテナ起動、Dockerコマンド実行も
- Docker Registry
- イメージ公開/共有
- 公式Docker HubもこのDocker Registryを使っている
- Docker Compose
- 複数コンテナ一元管理
- 複数のコンテナ構成情報をコードで定義し、コンテナ群を一元管理するツール
- Docker Machine
- Docker実行環境構築
- ローカルのVirtualBoxやクラウド環境のAWS EC2などにDocker実行環境をコマンドで自動生成するためのツール
- Dockerコンテナを動かすための機能
- Docker Swarm
- クラスタ管理
- 複数のDockerホストをクラスタ化するためのツール、集団を作るみたいな
- Kubernetes利用できる

AWSの、「Amazon EC2 Container Service」ではDocker実行環境のマネージドサービスを行っている。

Dockerが動く仕組み

Dockerはnamespaceでホスト上でコンテナを仮想的に隔離している。
namespaceでオブジェクトが衝突する可能性を減らす。sassで使ってる意味と同じ。

Linuxカーネルのnamespace機能は、Linuxオブジェクトに名前をつけることで6つの独立した環境を構築できる。
その6つは詳しく知らなくて良いけど、ファイル使うためにマウントさせたり、ユーザID作ったり、ネットワークの設定もろもろコンテナごとに独立して割り当ててくれるんだな。ということは理解しておいた方がよい。

リソース管理の仕組み(cgroups)

アプリは10%、デーモンは20% CPUの機能を使っていいよ 設定ができる。

cgroupsという機能でグループごとにCPUやメモリのリソースを振り分ける。
その制限をかけられた親の子も制限を受けるので、子が親の制限を超える設定を行っても制限がかかるしくみになっている。

ネットワークの構成

LinuxにDockerをインストールすると、サーバの物理NICがdocker0という仮想ブリッジネットワークに接続される。
172.17.0.0/16のサブネットマスクをもつプライベートIPアドレスが与えられる。
コンテナ内のeth0は、仮想NICがペアで割り当てられる。仮想NICはコンテナからみるとeth0として見える。
NICとは、ネットワークカード。LANケーブル刺すところ。eth0とは、NICのデバイス名のこと。

Dockerコンテナと外部ネットワークを通信するには、docker0と物理NICでパケットを転送するしくみが必要になる。それをNAPTの機能で接続する。

コンテナ起動時にコンテナ内で使用するWebサーバの80番ポートをホストOSの8080番ポートに転送するように設定する。
外部から8080ポートにアクセスすると、コンテナ内80番ポートに繋がる。

http://localhost:8080 → コンテナ内の80番ポートに

NAPT=IPマスカレード≠アドレス変換 1つのIPアドレスを複数のPCで共有する。

Dockerをインストールして使う

Mac,Windows対応してる方をインストールする。
公式ページ

Dockerの情報を確認する

バージョンの確認

$ docker version

実行環境の確認

$ docker system info

ディスク利用状況の確認

$ docker system df

Webサーバを立ち上げてみる

Nginxのイメージをダウンロードする

Docker HubにあるNginx公式イメージ

$ docker pull nginx

イメージがダウンロードできているかを確認

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              hogehoge            9 days ago          133MB
ubuntu              latest              hogehoge            12 months ago       64.2MB

REPOSITORYにnginxがあるのでダウンロードできている。

コンテナを作成して(サーバを)起動する

webserverという名前のコンテナを作る。
-pオプションでブラウザからHTTP(80番ポート)でアクセスを許可する。portのpかしら
nginxのイメージを使ってwebserverという名前のコンテナを生成する。

$ docker container run --name webserver -d -p 80:80 nginx
<ここにコンテナID(英数字のわりと長めの文字が表示される)>

http://localhost:80/
にアクセスして、Welcome to nginx!の表示が出たらサーバの起動が成功した。

起動しているコンテナの状態を確認する

$ docker container ps
CONTAINER ID      IMAGE   ~略~ PORTS                NAMES
0854671a9400      nginx   ~略~ 0.0.0.0:80->80/tcp   webserver

POSTSを見るとポートの設定が 80->80 にできていることが確認できた。

コンテナを停止する

$ docker stop webserver

コンテナを再び起動する

停止しているコンテナを起動する場合。

$ docker start webserver

イメージの操作

イメージをダウンロード

$ docker image pull [オプション] イメージ名[:タグ名]

バージョン違いなどで指定したい場合はタグ名をつける。
タグ名を省略すると最新版(latest)がダウンロードされる。

DockerHubのページにインストール用のコマンドを記述してくれているので、それを使うとよきかも。

イメージ一覧を表示

$ docker image ls [オプション] [レポジトリ名]
オプション 説明
-a すべてのイメージを表示
--digests ダイジェストを表示
-no-trunc 結果を全て表示
-q DockerイメージIDのみ表示

--digestsはダイジェストが付与されているイメージを表示したいときに使う。Dockerレジストリへアップロードしたらダイジェストが付与される。

イメージの詳細を確認

$ docker image inspect [イメージ名]

イメージID,作成日,Dockerバージョン,CPUのアーキテクチャを取得できる。
結果はJSON形式で表示される。

イメージにタグ(別名)を設定

目印になるためにタグをつけることができるが、イメージがコピーされるわけじゃないので注意すること。(imageIDは同じ)
命名規則は、以下の規則でユーザ名をつけること。

<dockerHubユーザ名> / イメージ名:[タグ名]

Docker Hubへアップロードするときもこの命名規則は守らないといけないみたい。

$ docker image tag nginx hazyuz/webserver:1.0

$ docker image ls
REPOSITORY          TAG          IMAGE ID            CREATED             SIZE
hazyuz/webserver    1.0          c39a868aad00        9 days ago          133MB
nginx               latest       c39a868aad00        9 days ago          133MB

誰が作って、どのイメージなのかがすぐにわかる。
→hazyuzが作った、Webサーバ用のイメージ

イメージを削除する

$ docker image rm [オプション] イメージ名かイメージID

$ docker image rm nginx

-fオプションをつけることでイメージを強制的に削除できる。

$ docker image rm -f nginx

未使用のイメージを削除する

$ docker image prune [オプション]

-aオプションで使用していないイメージをすべて削除
-fオプションでイメージを強制的に削除

使っていないDockerイメージは容量を圧迫するので、定期的に削除するとよい

コンテナの操作

イメージがあると、コンテナを生成できる。
コンテナはイメージの スナップショット のようなもの。

コンテナを生成する

$ docker container create

イメージからコンテナを生成する。
イメージの実態は、Dockerでサーバ機能を動かすために必要なディレクトリやファイル群のこと。
以下のコマンドで、コンテナを生成する。
(そのファイル群のスナップショットを撮る。)

コンテナを起動する準備が整った状態になった。起動はまだしていない。

コンテナを生成/起動する

イメージからコンテナを生成し、コンテナ上で任意のプロセスを起動できる。
Nginxなどのサーバープロセスをバックグラウンドで常時実行したり、ポート番号などのネットワークを設定すると外部からコンテナプロセスへアクセスできる。

バックグラウンドでサーバ機能を持たせる

-dオプションをつけると、バックグラウンドでコンテナを起動できる。
バックグラウンドで実行することをデタッチモードと言う。

バックグラウンドでネットワークの設定をして起動する。

$ docker container run --name webserver -d -p 8080:80 nginx

ホストへのアクセス http://localhost:8080 が、コンテナにの80番ポートへ転送される。

コンテナ内に入りでシェル(/bin/bash)を実行する。

$ docker container run -it --name "test2" centos /bin/bash
[root@aaaaaaa /]#

終了する時は exit入力。

稼働しているコンテナに入る場合はdocker container attach コンテナ識別子を使う。

その他

他にもオプションで、CPUやメモリを指定してコンテナを生成したり、ホストOSとコンテナ内のディレクトリを共有する設定もできる。環境変数なども。必要なときに都度調べる。

コンテナ一覧を確認

オプションなしで、稼働しているコンテナ一覧を表示

$ docker container ls [オプション]

-aオプションで停止しているコンテナ一覧を表示

$ docker container ls -a

コンテナの稼働状況を確認

CPUやメモリ状況を見たい時など

$ docker container stats [コンテナ識別子]

コンテナを起動

停止中のコンテナを起動する。

$ docker container start [コンテナ識別子]

コンテナを停止

起動しているコンテナを停止する。
コンテナを削除するときはコンテナを停止しておく必要がある。

$ docker container stop [コンテナ識別子]

コンテナを再起動するとき。

$ docker container restart [コンテナ識別子]

コンテナを削除

$ docker container rm [コンテナ識別子]

-fで強制的に削除

$ docker container rm -f [コンテナ識別子]

※ネットワークと稼働中コンテナの操作は次に

まとめ

Dockerの内部ネットワークの構成は仮想NICがコンテナに割り振られて、それをホストOSと繋げる設定をすることでコンテナのサーバへのアクセスが可能になる。
Dockerイメージというのは、ディレクトリやファイル群が集まっていてパッケージされたもので、重なったレイヤーのようになっている。
コンテナとは、イメージのスナップショット。

イメージとコンテナの関係

コンテナはイメージのスナップショットのようなもの。

これをgitHubで例えてみると、それぞれの機能を作ったブランチがレイヤーでそれをマージしたmasterブランチがイメージ。
masterブランチをローカル環境へpullすることが、コンテナを生成するということ。
新しいブランチをmasterから切る時(コンテナを削除して再び生成するときは)、前のイメージとは違った新しい内容(レイヤーが追加されているかもしれない)になっている場合がある。

なので、コンテナはスナップショットと本では表現していたのかな。違うかも。

?コンテナのコマンド部分なんですが、オプションが多くてよく使うものとあまり使わないものの区別がつかったので、使ったことがある(とか見たことのある)オプションしか記述してません。

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(ほぼインフラの話)プログラマのためのDocker教科書読む.1

※一度Zennに投稿したものです。次からこちらに投稿予定のため移行しました。

なぜDocker勉強したいのか

Dockerを使った案件に入ることがあります。(フロントはdocker-compose up -d叩くだけ)
ですが間隔が空いて作業するとき、ブランチきって立ち上げるとエラー画面になってしまったり、開発の方にDockerの設定が変更になったから再構築してねと連絡があったとき、とりあえず調べてコンテナ削除→イメージ削除→gitHubからpullして再構築...をしたのですが、なにがどうなってどうなったの?を無くしたかったです。

実は少し前にDockerやってみよって思ってどこかの記事を見てdockerfileからコンテナ起動したんですが、最近PCシャットダウンしても起動するとバックグラウンドで起動していたことに気づいて恐怖も感じました。
もしかしたらそのコンテナを止める時のコマンドをdocker-compose stopを使っていて、docker-compose downだったら大丈夫だったのかもしれない。多分。それも含めて知りたいと思いました。

インフラについて

サービスを作っても、インフラをしっかりしていないと運用し辛くなってしまう
しっかり運用できているのは運用設計をきちんとしてくれているから

システムに求められる要件

システムに求められる用件は大きく分けると2つ

機能要件

システムの機能、ソフトウェアでなにができるのかをまとめたもの

非機能要件

機能要件以外の要件、システムの性能や信頼性、セキュリティなど

システム基盤3つ(この上にアプリケーション)

システム基盤とは、アプリケーションを稼働させるために必要になるハードウェアやOS/ミドルウェアなどインフラのこと

サーバOS

Windows Server/Unix/Linuxなど。
システムを高速かつ安定に長時間稼働させるために特化している。

ミドルウェア

サーバOS上でサーバが特定の役割を果たすための機能を持つソフトウェアのこと。
Webサーバ/Webアプリケーションサーバ、データベースサーバ、システム管理ツールなどのこと。

ハードウェア/ネットワーク

データセンター(物理)、ネットワークはサーバを繋ぐ。

システムの利用形態

大きく分けて3つ
1. オンプレミス
自社でデータセンターを保有する。企業システムで多く利用されていた。工場とか多いかもしれない。
2. パブリッククラウド
インターネットで提供される。AWSなども。使った分だけ支払う。
3. プライベートクラウド
企業内データセンター、利用者が限定される。

システムの違い

クラウドが適しているサービス

  • トラフィックが変動しやすいサービス
    • 動画配信とか、予約システムなど。予想外にアクセスが多くなってしまった場合でも、すぐにシステムを準備することができる(その場合一時的に追加料金)。
  • 早くサービスインさせたいシステム
    • オンプレミスよりも初期投資が少なくて済む。

クラウドが適していないサービス

オンプレミスの方が向いている場合があるので、しっかり検討すること
- 高い可溶性、機密性、汎用的でない特殊なプラットフォーム
- 従業員向けシステムなど。トラフィックが予想しやすいので、計画を立てて強化できる。絶対に止まってはいけないサービス。(メンテナンスにしても、クラウドベンダーに左右されない)

ネットワーク

2つ。ネットワークの世界では、サーバやクライアントなどを識別するためにネットワークアドレスを使う。
1. MACアドレス
無線LANやインターフェースカードなどの部品に物理的に割り当てられた48ビットのアドレス。前半24ビットはメーカーを識別するもの。後半24ビットは重複しないように割り当てられている。16進数で先頭から2バイトずつ区切って表す。
データリンク層で使う。
2. IPアドレス
ネットワークに接続されたコンピュータに割り当てられた識別番号のこと。IPv4は、0-255までの10進数の数字を4つ並べて表す。192.168.1.1
IPv4では2の32乗までしか1つのネットワークに接続できないため、枯渇してしまう。社内ネットワークでは、プライベートアドレスとグローバルアドレスの変換をおこなう(NAT)機器を設置している。新しい方のIPv6では128ビット使えるので余裕ができる。

OSI参照モデル

ネットワーク技術の基本担っている。OSI基本参照モデルとは、ISOによって策定された通信機能を階層構造に分割した概念モデル。
7つ階層ある。
階層化することで相互接続性を確保している。

通信プロトコルは通信のための規約。お互いが意思疎通するための言語、のようなもの。

  • アプリケーション層 7
    • SSH、HTTP、DNSなどが代表プロトコル
  • トランスポート層 4
    • TCP、UDPのところ。TCPは確実、UDPは送りっぱなし。
  • ネットワーク層 3
    • IPのところ、IPを使い「どこからどこへ」を管理

LANケーブル→MACアドレス→ルータ→IP→TCP→データ送信のタイミング決めるやで→圧縮や文字コード表現形式決めるやで→アプリケーションのプロトコル規定するやで(HTTP,FTP)

ファイアウォール

システムを安全に稼働させるために、ファイアウォールで内部の安全を保つ。
内部と外部の通信を制御するためのもの。

  • パケットフィルタ型
    • 通過するパケットをポート番号やIPアドレスをもとにフィルタリングする。80番のみ通過してよい。それ以外は通信できないなどのルールを決めて制御。
  • プロキシサーバ
    • アプリケーションプロトコルレベルで外部との通信を代替し制御する。HTTPのかわりみたいなかんじ。

Linuxについて

Linuxカーネル

OSのコア部分のこと、Cやアセンブリで書かれている。
- デバイス管理
- デバイスドライバでソフトウェアを利用して制御。
- プロセス管理
- 命令を実行するときに、メモリ上に展開したプログラムをプロセスと言う。そのプロセスに識別子を付けて管理(PID)。CPUを効率的に割り当てる役割をする。
- メモリ管理
- プロセスが起動するとメモリ上にプログラムが展開されるが、そのプログラム上で利用するデータもメモリ上に展開される。それを物理メモリに効率よく割り当てる役割を持つ。実行終わったらそのメモリ領域を開放する。ただしメモリ容量には限界があるので、利用頻度低いデータ仮想メモリ領域に退避させる。スワップという。

シェル(殻)

Linuxカーネルを操作するためのもの。コマンドで命令する。
シェルで実行したい命令をまとめてテキストファイルにしたものをシェルスクリプトという。
制御構文使える。(if,for..)シェルはbashやzshなど。

Linuxファイルシステム

VFS:仮想ファイルシステム という仕組みでデータへの透過アクセス可能。
どこに保存されていようが、すべてはディレクトリの中にあるファイルとして取り出せる。(ハードディスクの中とかUSBの中とか意識しなくて良い)

Linuxのディレクトリ構成

各種コマンドや設定ファイルがディレクトリに配置される。このディレクトリ一覧をFHSという規格によって標準化されている。
Linuxディストリビューション(CentOSとかFedora,UbuntuなどのLinuxカーネルの外側が違うOS)によって差異はあるが、大体同じ。

セキュリティ機能

アカウントによる権限設定

rootユーザーと一般ユーザーで権限を設定できる。rootは特権ユーザですべての実行権限がある。
一般ユーザアカウントをグループ設定してパーミッションを設定も細かくできる。アクセス権限を決めることができる。
FTPでアップしたらたまにパーミッションで制限かかってて表示されないときがあるのと多分同じ。

その他たくさんのセキュリティ対策がある

ミドルウェアについて

アプリを起動させるためにはハードウェア/ネットワーク/OSの基礎知識に加えてミドルウェアの知識も必要

Webサーバ/Webアプリケーションサーバ

httpリクエストを受け、Webコンテンツ(html,cssなど)をレスポンスとして返したり、他のサーバサイドプログラムを呼び出したりする機能を持つ。
Apache,Nginxなど

データベースサーバ

データ管理するためのミドルウェア。DBMS。
MySQL,PostgreSQL(ぽすとぐれーすきゅーえる),OracleDatabase

リレーショナルデータベースとはデータを2次元の表の形式で管理しているデータベースのこと。複数の表を結合して利用できる。(リレーション)

NoSQL

RDBMSとは異なる形式。大量データの蓄積や並列処理を得意とするため、多数のユーザーからのアクセスを処理する必要がある。XMLデータベースオンラインシステムなどで広く利用される。
MongoDB,Redis

システム監視ツール

システムを安定稼働させるため。
Zabbix,Datadog,Mackerel(はてな)

インフラ構成について

クラウドシステムの登場やさまざまな技術分岐により、オンプレミスでは難しかったサーバやネットワークを構築したり、それをすぐに破棄したりできるようになった。
変更履歴も管理する必要がなくなった。今動作しているインフラの状態を管理すればよいというように変化してきた。

コードによる構成管理

パラメータシート(インフラにおける詳細設計書やプログラム設計書のようなもの)を使っていたが、管理が不十分場合構成の変更をしようとしたらうまく動いてくれないことがあった。最悪セキュリティインシデントを引き起こしてしまう。

それをコードで構築し、gitで管理することで、本番で変更があってもgitにログが残っている状態になり変更履歴も管理できる。メッセージも残しておける。
属人化を排除できる、共有も楽、誰が実行しても同じ状態になる。

DockerではDockerfileというファイルにインフラの構成情報を記述することができる。

代表的なインフラ構成管理ツール

OSの起動を自動化するツール

仮想環境作るVagrantとか

OSやミドルウェアの設定を自動化するツール

データベースサーバ/Webサーバ/監視エージェントなどのミドルウェアのインストールやバージョン管理、OSやミドルウェア設定ファイルやファイアウォールの設定などを自動化するためのツール
Chef,Ansibleとか

複数サーバの管理を自動化するツール

大規模なシスタムを構成するサーバは複数台にわたる。この分散しているサーバを管理するためのツール。
コンテナオーケストレーションツールのKubernetesはコンテナ仮想環境において複数のコンテナを総合管理するツール。

まとめ

Dockerを使うと環境が同じにできるよ。という利点だけではなく、標準化することで属人化を防ぐという利点もある。

インフラ知識は本当に苦手です、どの本や記事でも初めの方に書いてあるOSI参照モデルのイメージがつかめなくて難しく感じます。読むたびに、ああなんだったっけこれ...と調べ始めることからスタートしているのでそろそろつかみたいです。

自分はフロントの人なので、いつかフロント側から見るDockerでまとめられたらいいなぁと思っています。

参考文献

プログラマのためのDocker教科書 第2版

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Joget DXを始める方法

Joget DXを始める方法

はじめに

macOS環境の記事ですが、Windows環境も同じ手順になります。環境依存の部分は読み替えてお試しください。

目的

この記事を最後まで読むと、次のことができるようになります。

No. 概要 備考
1 Joget DXのインストール
2 Joget DXの学び方

実行環境

環境 Ver.
macOS Catalina 10.15.6
Docker 19.03.13

関連する記事

Joget DXとは

  • オープンソース
  • ローコード開発プラットフォーム
  • クラウドやモバイルで動作するWEBアプリの構築が可能
  • ワークフローの自動化が可能
  • 既存アプリのテンプレートを使用して独自アプリの構築が可能
  • JogetMarketplaceから新しいアプリやプラグインをダウンロードし拡張することが可能

Joget DXのインストール

Community版(無料)のインストール

Docker Pull Command

command.sh
docker pull jogetworkflow/joget-community

Case1: Run Joget with Embedded MySQL

command.sh
docker run -d -p 8080:8080 -v /var/lib/mysql --name joget jogetworkflow/joget-community

Case2: Run Joget with Linked MySQL and Container Mounted Volume

command.sh
docker volume create jogetdata
docker run -d --name jogetdb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=jwdb -e MYSQL_USER=joget -e MYSQL_PASSWORD=joget -e MYSQL_DATABASE=jwdb mysql:5.7
docker run -d --link jogetdb:jwdb --name joget -p 8080:8080 -e MYSQL_HOST=jwdb -e MYSQL_DATABASE=jwdb -e MYSQL_PORT=3306 -e MYSQL_USER=joget -e MYSQL_PASSWORD=joget --mount source=jogetdata,target=/opt/joget/wflow jogetworkflow/joget-community

Joget DXの起動

Joget DXのログイン

  1. Login > Username:, Password: 入力 > Submit
Username: Password:
admin admin

Joget DXの学び方

oget Knowledge Base

Joget Academy

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsのDocker化 〜その2〜

とりあえず、Railsアプリケーションを動かしてみる

まずは、どういうところに環境依存があるのか、また何がめんどくさかったのか思い出すために、
Railsアプリケーションをcloneしてlocal環境で動かすところまでやってみましょう。

■sample project
https://github.com/k-tetsuhiro/rails_docker_sample

こちらはruby 2.7.2と Rails 6.0.3.4 で作成されたsampleアプリです。
これを好きなところにgit cloneしてみてください。
これを bundle exec rails s で動かせるところまで持っていってみてください!
動かすまでに様々な問題点が出てくると思います。

出てくる問題点

まずはlocalのRubyのバージョンに2.7.2が入っているでしょうか?
rbenvを使用してる場合 rbenv versions で確認できます。

$ rbenv versions
  system
  2.3.8
  2.6.3
  2.6.5
  2.6.6
  2.7.0
  2.7.1
* 2.7.2 (set by /Users/kakuno/.rbenv/version)

どうでしょうか?
2.7.2が入ってない場合、まずlocal環境にruby2.7.2のインストールが必要になります。

さっそく環境依存が出てきてしまいました!!

この先も同じような環境依存が出てくる

起動するまでにlocalのこのような環境依存にこまるかと思います
・rubyのversion
・Railsのversion
・MySQLのversion
・yarnのversion
etc...

その環境依存 dockerで解決しよう!

というわけでここで出てくるのがdockerです!

誰かが環境を整えたRailsアプリケーション
それをimageとして保存しちゃおう!!

すべての環境(Ruby, Rails, MySQL, etc...)を込み込みでimageにしてしまえば、そもそも環境依存はおきないよね!
というイメージです!

更に利点として、local環境がMacだろうがWindowsだろうが、実際にRubyやRailsが入っているのはdockerのimageなので、どのマシンでも関係なく動きます!

dockerで動かしてみる

dockerで動かすことにすごいメリットを感じますね!
では次回はどうしたら今のRailsアプリケーションをdockerで動かすことができるのか?
ここを説明していきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerについて調べる

仮想マシンとコンテナの違い

参考

コレ1枚で分かる「仮想マシンとコンテナの違い」

結論

  • コンテナは各環境にOSが不要
  • コンテナがOSの違いを吸収。ことなる環境への移植が簡単

Docker入門

参考

コレ1枚で分かる「Docker」
Docker入門(第一回)~Dockerとは何か、何が良いのか~

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS cliでECRにpushするときに再認証を求められる&loginが400 bad requestで弾かれる

エラー内容

docker push ********.dkr.ecr.region.amazonaws.com/****:TAG

ECRにpushしようとすると

denied: Your authorization token has expired. Reauthenticate and try again.

トークンが期限切れと言われた。再度ログインします。

ログインする

aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin https://<id>.dkr.ecr.<region>.amazonaws.com

ちょっとハマってしまったポイントがあります。

  • get-login-passwordには明示的にregionが必要
  • get-login-passwordとdocker loginのregionが一致していなければいけない

さもないと400 bad requestが返ってきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KubernetesでデプロイしているPodをImage化する方法

kubectl get pod でPod名を確認します。

$ kubectl get pod
NAME                                         READY   STATUS    RESTARTS   AGE
oai                                         1/1     Running   0          28d

docker ps でNameからk8s_Pod名 というものを探し出し、それのコンテナのIDを確認します。

$ docker ps
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS               NAMES
6753a38ecfc9        791c227dd604                          "sleep infinity"         4 weeks ago         Up 4 weeks                              k8s_oai

commitをして、イメージ化します。

$ docker commit 6753a38ecfc9 output_name

docker images でイメージ化されたimageを確認します。

$ docker image
REPOSITORY   TAG   IMAGE ID  CREATED  SIZE
output_name  ***   ***       ***      ***
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCode+WSL2+Dockerによるリモート開発環境の構築 (devcontainer.json概訳付き)

はじめに

複数プロジェクトを同時に開発していたりすると依存するライブラリ等がコンフリクトしたり、別の開発者に展開する際に環境構築手順を作らないといけなかったりと地味に時間がかかっています。
またデプロイする際もコンテナで実施することも徐々に増えてきているので、初めからコンテナ上で開発した方がいいよねっていうことでVSCodeの拡張機能「Remote - Containers」を利用したリモート開発環境を構築したので、それについて紹介いたします。

今回実施した内容は以下の通りとなっています。

  1. 環境構築 (SSH/Docker Context)
  2. リモート上でのWebアプリ開発・デバッグ
  3. 設定ではまったこと
  4. (参考)devcontainerイメージ一覧
  5. (参考)devcontainer.json設定一覧

構築した環境

構築した環境は以下の通り。WSL2のUbuntu上にDockerをインストールし、そこに接続する形をとっています。
別サーバー上にDockerをインストールしてリモート開発する場合も、ほぼ手順は同じかと思います。
※透過プロキシが入っているのはプロキシ設定を省略するのが目的です。もし必要があれば別記事についても参照ください。
環境概要

1. 環境構築

標準の手順では、VSCodeのsetting.jsonにDockerの接続先を設定していますが、ここでは接続先を切り替えることを考慮してDocker Contextによる接続先の設定、およびDocker拡張機能によるコンテキストの設定方法を説明します。

1.1. SSH認証キーの作成と設定

Docker Contextによる接続では、パスワードによる認証に対応していないため、SSH認証キーを作成しそれぞれ設定します。
ここでは、Windows 10に付属しているOpenSSHを利用します。
OpenSSHをインストールされていない場合は「設定→アプリ→オプション機能→機能の追加」よりOpenSSH サーバー、およびOpenSSH クライアントをインストールしてください。

Local(PowerShell)
> ssh-keygen -t ecdsa -f keyfile

作成された公開鍵id_ecdsa.pubをリモート上に転送し、~/.ssh/authorized_keysに登録します。

Remote(WSL2)
$ cat keyfile.pub >> /home/<user>/.ssh/authorized_keys
$ chmod 600 /home/<user>//.ssh/authorized_keys

もしWSL2を利用されている場合は、dockerと同様に下記の通りSSHのサービスを起動し必要があればWindowsのポートフォワードもしてください。

Remote(WSL2)
$ sudo service ssh start

1.2. Docker Contextの作成

作成した認証キーの登録し、Docker Contextの作成を行います。最後のdockerコマンドで作成したContextを指定し、リモート上の実行中のコンテナ一覧が表示されれば正常に作成されています。

Local(PowerShell)
> sc config ssh-agent start=auto
> net start ssh-agent
> ssh-add ./keyfile

> docker context create remote1 --docker "host=ssh://<user>@<remote hostname>:<port>"
> docker --context=remote1 ps

※ssh-addでエラーが発生した場合、OpenSSH サーバーがインストールされているか確認してください(参考記事4)。

1.3. VSCode拡張機能のインストール

VSCodeには以下の2つの拡張機能をインストールしてください。

  • Docker
  • Remote - Containers

Docker拡張機能をインストールすると新たにタブが追加されるので、そのタブを開きCONTEXTSを開くとDocker Contextの一覧が表示されます。
ここで先ほど作成したContextを利用するように設定(右クリック→USE)します。Context横に接続マークが表示されていれば設定完了です。

Docker Contextの選択

2. リモートでのWebアプリ開発・デバッグ

ここではASP.net coreを例に、リモート上でWebアプリの開発、およびデバッグするまでの手順を記載いたします。
リモート上になりますので、ローカルファイルシステムのマウントは出来ず、図に記載した通りリモート上のファイルシステムをマウントするように設定します。

2.1. コンテナ開発設定の初期化

  • Ctrl+Shift+Pを押下しコマンドパレット表示後、Remote-Containers: Add Development Container Configuration Filesを選択します。
    コンテナ開発設定の追加

  • 追加する設定テンプレート一覧が表示されます。ここではShow All Definitions...をクリックし、言語別のテンプレートを表示させます。
    テンプレート一覧(初期)

  • C# を選択すると、.net coreのバージョンやオプションについて聞かれますが、デフォルトのままでOKボタンを押下します。
    テンプレート一覧(言語別)

  • 選択したテンプレートにてdevcontainer.jsonDockerfile等が作成されれば初期化は完了です。
    リモートコンテナプロジェクト設定完了

2.2. プロジェクトの設定変更

リモート上へのマウント設定の追加

データを保持するために、リモート上にプロジェクト用のフォルダを作成します。
ここでは仮にログインユーザのホームディレクトリにworkspacesフォルダを作成し、また、その下に項2.1で初期化したフォルダと同名のフォルダを作成します。
これはデフォルトの設定では、コンテナ起動後のVSCode接続時にワークスペースフォルダ中にあるプロジェクトフォルダを開きにいくためです。

Remote
$ mkdir -p  /home/<user>/workspaces/<Project Folder Name>

devcontainer.jsonworkspaceMountの項目を追加し、上記のworkspacesフォルダとのマッピングを追加します。
target=の設定については、Dockerfileで利用したベースイメージの仕様になります。

devcontainer.json
{
    // ---  ----
    "workspaceMount": "source=/home/<user>/workspaces,target=/workspaces,type=bind,consistency=cached",
    // ---  ----
}

ユーザ設定の変更

次にリモート上のユーザと、コンテナ上で実行されるユーザの整合性を取るようにします。
ここの設定を間違えると、読み書きが出来なかったり、リモート上でファイルを開けなかったりするので注意してください。
はじめにリモートホスト上にログインしたユーザのuidgidを確認します。
※下はユーザremoteでログインした場合一例になります。

Remote
$ id
uid=1001(remote) gid=1001(remote) groups=1001(remote),999(docker)

確認した上記のuidgidでコンテナ上にユーザを作成します。その他のオプションについてはMSガイドを参照してください。
ここでは試しにdevconというユーザ名で作成しています。

Dockerfile
ARG USERNAME=devcon
ARG USER_UID=1001
ARG USER_GID=$USER_UID

# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
    && apt-get update \
    && apt-get install -y sudo \
    && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
    && chmod 0440 /etc/sudoers.d/$USERNAME

USER $USERNAME

またdevcontainer.jsonにユーザ名を設定します。

devcontainer.json
{
    // ---  ----
    "remoteUser": "devcon"
}

以上で設定の変更は完了です。
後は左下の><アイコンをクリックして出てきたメニューよりRemote-Containers: Reopen in Containerをクリックすると、Dockerイメージがビルドされコンテナの起動とリモート接続が開始されます。

2.3. コンテナでの開発

ここまでくると通常のローカルでの開発とほぼ同じです。
起動したVSCodeからターミナルを開き、dotnetコマンドでプロジェクトを初期化し、F5キーを押下すればデバッグが開始され、ブラウザからの参照やブレークポイントによる変数内容の確認等も可能になってます。

  • プロジェクト初期化
Container
$ dotnet new react
  • Webアプリの参照
    Web画面

  • デバッグ・ブレークポイント
    デバッグ・ブレークポイント確認

上記の通り、VSCodeがデバッグ時にコンテナ上のポートを転送してくれるようになっています。
デバッグを開始した際、左下に「使用可能なポートがX個あります」と表示されていれば転送設定がされており、もしされていない場合はメッセージ部分をクリックすると下記のようなポート転送設定画面が開かれるので、ここに手動で追加してください。

実行時のポート検出

2.4. データのアップロード・ダウンロード

コンテナ上へのデータのアップロード・ダウンロードのVSCodeから行えます。
アップロードする場合は、VSCodeのエクスプローラーにファイルをドラッグ&ドロップするとアップロードでき、ダウンロードする場合は右クリックすると下記の通りダウンロードメニューがあるので、そこから実施できます。

エクスプローラー

3. 設定ではまったこと

ネットワーク環境が異なる場合の注意点 (主にプロキシ設定)

リモート開発時はローカルとネットワーク環境等が異なると思いますが、標準だとVSCode/gitについて設定が引き継がれるようになっています。
このためローカルでプロキシの設定をしていたりすると、一部プラグインがその設定により正常に動作しなかったりするので、その設定を外す必要があります。
これらの設定を外す場合はdevcontainer.jsonを修正し、settingsでVSCodeの設定を、'postStartCommand'でgitの設定を変更するようにします。

devcontainer.jsonを修正後は、設定を反映させるためにVSCodeのウィンドウの再読み込みを行ってください。
これまでの設定を実施したdevcontainer.jsonは以下の通りとなります。

devcontainer.json
{
    "name": "csharp_container",
    "build": {
        "dockerfile": "Dockerfile",
        "args": { 
            "VARIANT": "3.1",
            "INSTALL_NODE": "true",
            "NODE_VERSION": "lts/*",
            "INSTALL_AZURE_CLI": "false"
        }
    },
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash",
        "http.proxySupport": "off"
    },
    "postStartCommand": "git config --global --unset http.proxy && git config --global --unset https.proxy",
    "extensions": [
        "ms-dotnettools.csharp"
    ],
    "workspaceMount": "source=/home/remote/workspaces,target=/workspaces,type=bind,consistency=cached",
    "remoteUser": "devcon"
}

設定失敗時のコンテナイメージのリビルド

Docerfiledevcontainer.jsonの設定について失敗した場合、メニューのRebuild Containerが正常に動作しないことがあります。
この場合はvsc-<Project Folder Name>という名称でイメージが作成されているので、それを手動で削除します。
VSCodeのDockerタブのCONTAINERSより、該当する名称のものを探しRemove...で削除してください。

複数PCからの接続時の注意点

Remote Containers拡張機能では、コンテナイメージの識別に、プロジェクトフォルダのパスを利用している模様です(※20/11/20時点)。
このため注意点として、複数PC(ユーザ)から同一のリモートホスト(Docker)に接続する場合、プロジェクトのパスを変更しなければならない点が挙げられます。
プロジェクトフォルダのパスが同一だった場合でもVSCodeは立ち上がりますが、同一コンテナ上に接続しに行っているためデバッグ時にポートの競合が起きる等の問題が発生してしまいます。

remoteUser指定時の挙動について

devcontainer.jsonの設定説明を見てみると、uid, gidが自動的にマッピングしてくれるとの記載がありますが、そのような挙動は見られませんでした。
利用方法が悪いのかバグなのかは調べきれていませんが、可能な限りDocker上で実行するユーザの設定をしたほうが現時点では無難な感じです。

(参考)devcontainerイメージ一覧

参考までにリモート開発用コンテナ一覧について転記します。
最新のイメージ一覧はこちらから参照してください。

  • mcr.microsoft.com/vscode/devcontainers/base
    • alpine, alpine-3.10, alpine-3.11, alpine-3.12
    • debian, buster, debian-10, stretch, debian-9
    • ubuntu, focal, ubuntu-20.04, bionic, ubuntu-18.04
  • mcr.microsoft.com/vscode/devcontainers/cpp - buster, debian-10, stretch, debian-9
  • mcr.microsoft.com/vscode/devcontainers/dotnetcore - 3.1, 2.1
  • mcr.microsoft.com/vscode/devcontainers/go - 1, 1.15, 1.14
  • mcr.microsoft.com/vscode/devcontainers/java - 8, 11, 14
  • mcr.microsoft.com/vscode/devcontainers/javascript-node - 14, 12, 10
  • mcr.microsoft.com/vscode/devcontainers/php - 7, 7.4, 7.3
  • mcr.microsoft.com/vscode/devcontainers/python - 3, 3.8, 3.7, 3.6
  • mcr.microsoft.com/vscode/devcontainers/anaconda - 3
  • mcr.microsoft.com/vscode/devcontainers/miniconda - 3
  • mcr.microsoft.com/vscode/devcontainers/ruby - 2, 2.7, 2.6, 2.6
  • mcr.microsoft.com/vscode/devcontainers/rust
  • mcr.microsoft.com/vscode/devcontainers/typescript-node - 14, 12, 10
  • mcr.microsoft.com/vscode/devcontainers/universal

(参考)devcontainer.json設定一覧

参考までにdevcontainer.jsonで設定可能な項目の一覧について記載します。
最新の設定はこちらを参照してください。

  • 一般設定項目
設定項目 詳細
name string リモート接続時の表示名を設定します。
extensions array コンテナの作成時にコンテナ内にインストールする必要がある拡張機能を指定する拡張機能IDの配列を設定します。
settings object settings.jsonに設定する内容。コンテナ/マシン固有のデフォルト値を追加。
forwardPorts array コンテナ内からローカルマシンに転送する必要のあるポートの配列を設定します。
postCreateCommand string, array コンテナ作成後にコンテナ内で実行するコマンド文字列またはコマンド引数のリストを設定します。workspaceFolderがカレントディレクトリとなっており、ソースフォルダがマウントされた後に実行されるため、フォルダ内のシェルスクリプト等を実行することも可能です。。
postStartCommand string, array コンテナの開始時に実行するコマンド文字列またはコマンド引数のリストを設定します。その他仕様はpostCreateCommandと同様です。。
postAttachCommand string, array VSCodeが実行中のコンテナにアタッチされた後に実行するコマンド文字列またはコマンド引数のリストを設定します。その他仕様はpostCreateCommandと同様です。
initializeCommand string, array コンテナイメージ構築前、およびコンテナが作成または開始された際にローカル上で実行するコマンド文字列またはコマンド引数のリスト。コマンドはworkspaceFolderにて実行されます。
userEnvProbe enum タスクのデバッグや実行の際に利用するユーザ環境変数について取得するための方法を指定します。
none(デフォルト), interactiveShell. loginShell. loginInteractiveShellが設定可能で、interactiveShellでは/etc/bash.bashrc,.bashrcに設定された内容が、loginShellでは「rc」ファイル、および/etc/profile, .profileに設定された内容が含まれています。
デフォルト値のnone以外のモードでは起動が遅くなる可能性があります。
devPort integer VS CodeServerがコンテナで使用する特ポートを設定します。デフォルトではランダムに設定されます。
  • 共通項目(Dockerイメージ、Dockerfile、Docker Compose)
設定項目 詳細
remoteEnv object VSCode(またはターミナル等のサブプロセス)の環境変数を設定または上書きする名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。[ターミナル]> [統合:環境の継承]が設定でチェックされていることを確認してください。
例:"remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path", "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
remoteUser string コンテナ内で実行されるVSCodeのユーザを設定します(ターミナル、タスク、デバッグ等のサブプロセス含む)。VSCodeが再起動されたとき(またはウィンドウがリロードされたとき)に更新が適用されます。
[コンテナ]
デフォルトはcontainerUserが設定されます。Linuxでは、指定されたコンテナユーザのUID / GIDは、ローカルユーザのUID / GIDと一致するように更新され、バインドマウントでのアクセス許可の問題を回避します。UID / GIDの更新を適用するには、コンテナを再作成する必要があります。
[Compose]
デフォルトではDocker Composeファイルで設定された実行ユーザになります。
workspaceFolder string コンテナに接続時にVSCodeが開くデフォルトのパスを設定します。
[コンテナ] 通常workspaceMountと組み合わせて使用​​します。ソースコードのマウントしたパスです。
[Compose] コンテナ内でソースコードフォルダをマウントしたパスを設定します。デフォルトは"/"
shutdownAction enum ウィンドウが閉じられた(シャットダウンされた)際にコンテナを停止するかどうか。
none, stopContainer(コンテナ時デフォルト), stopCompose(Compose時デフォルト)
  • Dockerイメージ、Dockerfileのみ
設定項目 詳細
image string Dockerイメージを利用する場合必須。
VSCodeがコンテナを作成する際のコンテナレジストリ内のイメージの名前を指定します。
build.dockerfile string Dockerfileを使用する場合に必須。
コンテナの内容を定義するDockerfileの場所。パスはdevcontainer.jsonファイルからの相対パスを記載します。
build.context string docker buildを実行するdevcontainer.jsonからの相対パスを設定します。
build.args object Dockerfileをビルドするときに渡されるDockerイメージビルド引数を含む名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。
例:"build": { "args": { "MYARG": "MYVALUE", "MYARGFROMENVVAR": "${localEnv:VARIABLE_NAME}" } }
build.target string Dockerfileビルドするときに渡されるターゲット文字列を指定します。
例:"build": { "target": "development" }
appPorts integer, string, array 通常はforwardPortsプロパティを使用すること推奨。
このプロパティでは、コンテナのポートフォワード設定についても実施します。
containerEnv object コンテナの環境変数を設定または上書きする名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。
例:"containerEnv": { "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
containerUser string コンテナで実行される命令について指定したユーザに設定します。デフォルトは、rootまたはDockerfileUSERで指定したユーザになります。
Linuxでは、指定されたコンテナユーザのUID / GIDは、ローカルユーザのUID / GIDと一致するように更新され、バインドマウントでのアクセス許可の問題を回避します
updateRemoteUserUID boolean Linuxでは、containerUserまたはremoteUserが指定されている場合、バインドマウントでのアクセス許可の問題を回避するために、コンテナユーザのUID / GIDがローカルユーザのUID / GIDと一致するように更新されます。デフォルトはtrue
mounts array 作成時にコンテナに追加する追加のマウントポイントの配列。DockerCLIのmountフラグと同じ値をサポートします。環境変数や事前定義された変数についても参照可能です。
例:"mounts": ["source=${localWorkspaceFolder}/app-scripts,target=/usr/local/share/app-scripts,type=bind,consistency=cached"]
workspaceMount string コンテナの作成時に、ワークスペースのデフォルトのローカルマウントポイントを上書きします。DockerCLIのmountフラグと同じ値をサポートします。主に、リモートコンテナの構成やディスクパフォ​​ーマンスを向上させる際に変更します。環境変数や事前定義された変数についても参照可能です。
runArgs array コンテナの実行時に使用するDockerCLI引数の配列。デフォルトは[]。
overrideCommand boolean コンテナのデフォルトコマンドを上書きするか設定します。
デフォルトではtrueに設定されており、/bin/sh -c "while sleep 1000; do :; done"が実行されます。
  • Docker Composeのみ
設定項目 詳細
dockerComposeFile string, array Compose時必須。DockerComposeファイルへのパスまたはパス配列を指定します。パスはdevcontainer.jsonからの相対パスになります。配列で定義した場合、後で定義された内容で上書きされます。
.envファイルはデフォルトではプロジェクトのルートから取得されますが、DockerComposeファイルにて別のパスの指定も可能です。
service string Compose時必須。実行後に接続するサービス名。
runServices array 開始するDocker Compose設定内のサービス名配列。shutdownActionnoneに設定しない限り、VSCode終了時に、これらも停止されます。デフォルトではすべてのサービスが対象です。

最後に

Docker関係の知識は多少必要かもしれませんが、思っていた以上に簡単に、また特段の制限なくWebアプリ等の開発環境が構築可能なことに驚きました。
また外注等の開発者の入れ替わりが激しい場合も容易に開発環境を複製することが出来ますので、かなりメリットが大きいと感じています。
今回記載した記事が、何かしら皆さまのお役に立てれば幸いです。

関連記事

参考記事

  1. VSCodeでリモートホスト上のDocker上で開発する - Qiita
  2. Visual Studio Code Remote Development
  3. Developing inside a Container using Visual Studio Code Remote Development
  4. Can't acess ssh-agent · Issue #1491 · PowerShell/Win32-OpenSSH
  5. VS Code Remote Development Container Images - Docker Hub

商標

  • Microsoft、Windows、Visual Studioは,米国Microsoft Corporationの米国およびその他の国における登録商標または商標です。
  • Ubuntuは,Canonical Ltd.の商標または登録商標です。
  • DockerおよびDockerのロゴはDocker,Inc.の米国およびその他の国における商標または登録商標です。
  • その他記載の会社名、製品名、サービス名等はそれぞれの会社の商標または登録商標です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでDocker環境構築後にルーティング設定が効かなくなる時の対処法

1.まずはルートが存在するのか確認

php artisan route:list

2.httpd.confを確認する
sudo vim /etc/httpd/conf/httpd.conf

httpd.confの内容が以下になっているか確認。

DocumentRoot "/var/www/html/laravel/public/"


Allowoverride All

3.rewrite.loadがあるか確認してみる

ls /etc/apache2/mods-enabled/

a2enmod rewrite

4.再起動をしてrewrite.fileが追加されているか確認

service apache2 restart 又は apachectl restart

ls /etc/apache2/mods-enabled/

dockfileからRUNコマンドでできる方法もあるみたいですが、今回はこちらの方法でしました。

参考元
http://peacock.ky-3.net/laravel/laravel_404notfound

https://qiita.com/dokkoisho/items/03746e58d975bd7a35ec

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker環境構築後にルーティング設定が効かなくなる時の対処法

1.まずはルートが存在するのか確認

php artisan route:list

2.httpd.confを確認する
sudo vim /etc/httpd/conf/httpd.conf

httpd.confの内容が以下になっているか確認。

DocumentRoot "/var/www/html/laravel/public/"


Allowoverride All

3.rewrite.loadがあるか確認してみる

ls /etc/apache2/mods-enabled/

a2enmod rewrite

4.再起動をしてrewrite.fileが追加されているか確認

service apache2 restart 又は apachectl restart

ls /etc/apache2/mods-enabled/

dockfileからRUNコマンドでできる方法もあるみたいですが、今回はこちらの方法でしました。

参考元
http://peacock.ky-3.net/laravel/laravel_404notfound

https://qiita.com/dokkoisho/items/03746e58d975bd7a35ec

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コンテナとGithubを利用したWebシステム開発の効率化

はじめに

システムやアプリの開発をする際、Github上にリポジトリを作ってそこでソース管理することが多いが、実行環境がこれらのソースを直接的に見ていなかったり、開発環境はローカルで立てたりするため、手元では動いたが本番環境にアップロードすると失敗といった事が頻繁に起こっていた。
今回、ソースコードをGithub上に置き、そのソースコードを参照する様なWebサーバーコンテナができないかを試してみたので、本記事ではその内容をまとめる。

実行環境

【Docker導入環境】
  ・Ubuntu20.04 LTS(GCP上)
  ・docker19.03.13

【コンテナ環境】
  ・Image Ubuntu:20.04
  ・Apache2.4.41

試してみる事

docker上に2つのWebサーバー用コンテナを作成して、1つを本番用、もう1つを開発用とする。
本番用のコンテナはビルドする度に、GithubリポジトリのmainブランチからアプリコードをCloneする様にし、
開発用のコンテナはdevブランチからアプリコードをCloneするようにDockerfileを作成してみる。

手順

1.環境準備
2.Github上にリポジトリを作成
3.Apacheを起動させるまでのDockerfileを作成
4.Github上のコードを取得するDockerfileに修正

1.環境の準備

GCP上にVMインスタンスを作成
 ※イメージはUbuntu20.4 LTS

dockerのインストール
 ※【Dockerコンテナ内のUbuntuではsystemctlは使えない】の手順1を参考に。

2.Github上にリポジトリを作成

Github上で以下を実施する。

■Public用のリポジトリを作成 
 ※手順4のDockerfileの内容は、Publicリポジトリからクローンすることを前提としている。

■作成したリポジトリ内の直下に『App』フォルダを作成

■『App』フォルダ内にindex.htmlを作成
 ※中身は適当に記載

■開発用のブランチを切る
 ※手順4ではブランチ名は main(本番用)dev(開発用) を前提としている。

3.Apacheを起動させるまでのDockerfileを作成

DockerFile を作成する

$ sudo nano ./Dockerfile

※最初『DockerFile』というファイルを作成したが、"F" が大文字だったためビルドに失敗した。

Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="1.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

ビルドしてイメージを作成

$ docker image build -t websys:production ./

 ※今回、DockerFileはカレントディレクトリに作成しているためパス部分が ./ となっている。

イメージの確認

$ docker image ls

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
websys              production          5e35969b988e        15 seconds ago      67.3MB
ubuntu              18.10               9dc19675e327        16 months ago       67.3MB

上記のイメージを使ってコンテナ作成

$ docker container run -it -d -p 8080:80 --name ap1_server websys:production

以下のURLにアクセスして初期画面が開かれればOK!

http://[VMの外部IP(グローバルIPアドレス)]:8080/

4.Github上のコードを取得するDockerfileに作り直し

Github上にmainブランチとdevブランチがある前提で、本番環境はmainブランチからソースコードをクローンする様にし、開発環境はdevブランチからソースをクローンする様に作り直し。

本番環境、開発環境はクローン対象が違うため、それぞれDockerfileを用意する。

まずはディレクトリ作成

$ sudo mkdir ./main
$ sudo mkdir ./dev

ビルド時に反映させるサイトコンフィグの情報を作成

■本番環境用

$ sudo nano ./main/main_site.conf
main_site.conf
# Githubのリポジトリの階層構想により、DocumentoRootの場所は調整。

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/main/App
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

■開発環境用

$ sudo nano ./dev/dev_site.conf
dev_site.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/dev/App
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

DockerFile を作成し直し
 ※手順3のDockerfileは破棄してしまってOK。

■本番環境用のDockerfileを作成

$ sudo nano ./main/Dockerfile
Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="2.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 本番環境用開のサイト構築(この部分が開発環境とは異なる!)
ADD ./main_site.conf /etc/apache2/sites-available/
RUN git clone --depth 1 -b main https://github.com/Smiler5617/test_websys.git /var/www/html/main
RUN a2dissite 000-default
RUN a2ensite main_site

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

■開発環境用のDockerfileを作成

$ sudo nano ./dev/Dockerfile
Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="2.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 開発環境用のサイト構築(この部分が本番環境とは異なる!)
ADD ./dev_site.conf /etc/apache2/sites-available/
RUN git clone --depth 1 -b dev https://github.com/Smiler5617/test_websys.git /var/www/html/dev
RUN a2dissite 000-default
RUN a2ensite dev_site

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

それぞれのDockerfileをビルド

$ docker image build -t websys:main ./main/
$ docker image build -t websys:dev ./dev/

イメージの確認

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
websys              dev                 cee2d11ec02f        37 seconds ago      264MB
websys              main                7ac716953021        6 minutes ago       264MB
ubuntu              20.04               d70eaf7277ea        3 weeks ago         72.9MB

イメージよりコンテナ作成
 ※ポートのマッピングは本番環境と開発環境で変える。

$ docker container run -it -d -p 8080:80 --name ap_server websys:main
$ docker container run -it -d -p 8081:80 --name dev_ap_server websys:dev

ちゃんと起動できているか確認
 本番環境:http://[VMの外部IP(グローバルIPアドレス)]:8080/
 開発環境:http://[VMの外部IP(グローバルIPアドレス)]:8081/
 

試しにdevブランチでindex.htmlに変更を加えてimageを作り直したら、ちゃんと反映されているので今回やってみたかった事はできた。
 ※DockerfileのRUNコマンドの中でgit cloneの記述をしているので、イメージの作成タイミングでないとクローンをし直せない。

おまけ

上記にも記載した通り、ちょっとした修正でもイメージを作り直す必要があるので、ここら辺をもう少し簡易にできないのか試してみた。

方法としてはstartup.sh を作成して、そこの中で『git clone』と『Apacheの起動』をさせる命令を書く。そしてDokcerfileのCMDコマンドではstartup.shを実行させるだけ。

startup.shの作成

(本番環境用)
$ sudo nano ./main/startup.sh
startup.sh(本番環境用)
git clone --depth 1 -b main https://github.com/Smiler5617/test_websys.git /var/www/html/main
apachectl -D FOREGROUND
(開発環境用)
$ sudo nano ./dev/startup.sh
startup.sh(開発環境用)
git clone --depth 1 -b dev https://github.com/Smiler5617/test_websys.git /var/www/html/dev
apachectl -D FOREGROUND

Dockerfileの作成

Dockerfile(本番環境用)
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="3.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 必要ファイルを入れる
ADD ./main_site.conf /etc/apache2/sites-available/
ADD ./startup.sh /etc/apache2/

# デフォルトサイトからの切り替え
RUN a2dissite 000-default
RUN a2ensite main_site

# ポート開放
EXPOSE 80

# イメージからコンテナを作成するタイミングでシェルを実行
CMD ["bash", "/etc/apache2/startup.sh "]
Dockerfile(開発環境用)
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="3.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 必要ファイルを入れる
ADD ./dev_site.conf /etc/apache2/sites-available/
ADD ./startup.sh /etc/apache2/

# デフォルトサイトからの切り替え
RUN a2dissite 000-default
RUN a2ensite dev_site

# ポート開放
EXPOSE 80

# イメージからコンテナを作成するタイミングでシェルを実行
CMD ["bash", "/etc/apache2/startup.sh "]

ビルドしてイメージ作成

$ docker image build -t websys:main ./main/
$ docker image build -t websys:dev ./dev/

イメージよりコンテナ作成

$ docker container run -it -d -p 8080:80 --name ap_server websys:main
$ docker container run -it -d -p 8081:80 --name dev_ap_server websys:dev

この改良により、わざわざイメージから作り直さずにコンテナだけ作成し直せばソースコードの更新ができるようになった。

以上!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コンテナとGitを利用したWebシステム開発の効率化

はじめに

システムやアプリの開発をする際、Github上にリポジトリを作ってそこでソース管理することが多いが、実行環境がこれらのソースを直接的に見ていなかったり、開発環境はローカルで立てたりするため、手元では動いたが本番環境にアップロードすると失敗といった事が頻繁に起こっていた。
今回、ソースコードをGithub上に置き、そのソースコードを参照する様なWebサーバーコンテナができないかを試してみたので、本記事ではその内容をまとめる。

実行環境

【Docker導入環境】
  ・Ubuntu20.04 LTS(GCP上)
  ・docker19.03.13

【コンテナ環境】
  ・Image Ubuntu:20.04
  ・Apache2.4.41

試してみる事

docker上に2つのWebサーバー用コンテナを作成して、1つを本番用、もう1つを開発用とする。
本番用のコンテナはビルドする度に、GithubリポジトリのmainブランチからアプリコードをCloneする様にし、
開発用のコンテナはdevブランチからアプリコードをCloneするようにDockerfileを作成してみる。

手順

1.環境準備
2.Github上にリポジトリを作成
3.Apacheを起動させるまでのDockerfileを作成
4.Github上のコードを取得するDockerfileに修正

1.環境の準備

GCP上にVMインスタンスを作成
 ※イメージはUbuntu20.4 LTS

dockerのインストール
 ※【Dockerコンテナ内のUbuntuではsystemctlは使えない】の手順1を参考に。

2.Github上にリポジトリを作成

Github上で以下を実施する。

■Public用のリポジトリを作成 
 ※手順4のDockerfileの内容は、Publicリポジトリからクローンすることを前提としている。

■作成したリポジトリ内の直下に『App』フォルダを作成

■『App』フォルダ内にindex.htmlを作成
 ※中身は適当に記載

■開発用のブランチを切る
 ※手順4ではブランチ名は main(本番用)dev(開発用) を前提としている。

3.Apacheを起動させるまでのDockerfileを作成

DockerFile を作成する

$ sudo nano ./Dockerfile

※最初『DockerFile』というファイルを作成したが、"F" が大文字だったためビルドに失敗した。

Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="1.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

ビルドしてイメージを作成

$ docker image build -t websys:production ./

 ※今回、DockerFileはカレントディレクトリに作成しているためパス部分が ./ となっている。

イメージの確認

$ docker image ls

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
websys              production          5e35969b988e        15 seconds ago      67.3MB
ubuntu              18.10               9dc19675e327        16 months ago       67.3MB

上記のイメージを使ってコンテナ作成

$ docker container run -it -d -p 8080:80 --name ap1_server websys:production

以下のURLにアクセスして初期画面が開かれればOK!

http://[VMの外部IP(グローバルIPアドレス)]:8080/

4.Github上のコードを取得するDockerfileに作り直し

Github上にmainブランチとdevブランチがある前提で、本番環境はmainブランチからソースコードをクローンする様にし、開発環境はdevブランチからソースをクローンする様に作り直し。

本番環境、開発環境はクローン対象が違うため、それぞれDockerfileを用意する。

まずはディレクトリ作成

$ sudo mkdir ./main
$ sudo mkdir ./dev

ビルド時に反映させるサイトコンフィグの情報を作成

■本番環境用

$ sudo nano ./main/main_site.conf
main_site.conf
# Githubのリポジトリの階層構想により、DocumentoRootの場所は調整。

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/main/App
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

■開発環境用

$ sudo nano ./dev/dev_site.conf
dev_site.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/dev/App
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

DockerFile を作成し直し
 ※手順3のDockerfileは破棄してしまってOK。

■本番環境用のDockerfileを作成

$ sudo nano ./main/Dockerfile
Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="2.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 本番環境用のサイト構築(この部分が開発環境とは異なる!)
COPY ./main_site.conf /etc/apache2/sites-available/
RUN git clone --depth 1 -b main https://github.com/Smiler5617/test_websys.git /var/www/html/main
RUN a2dissite 000-default
RUN a2ensite main_site

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

■開発環境用のDockerfileを作成

$ sudo nano ./dev/Dockerfile
Dockerfile
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="2.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 開発環境用のサイト構築(この部分が本番環境とは異なる!)
COPY ./dev_site.conf /etc/apache2/sites-available/
RUN git clone --depth 1 -b dev https://github.com/Smiler5617/test_websys.git /var/www/html/dev
RUN a2dissite 000-default
RUN a2ensite dev_site

# ポート開放
EXPOSE 80

CMD ["apachectl", "-D", "FOREGROUND"]

それぞれのDockerfileをビルド

$ docker image build -t websys:main ./main/
$ docker image build -t websys:dev ./dev/

イメージの確認

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
websys              dev                 cee2d11ec02f        37 seconds ago      264MB
websys              main                7ac716953021        6 minutes ago       264MB
ubuntu              20.04               d70eaf7277ea        3 weeks ago         72.9MB

イメージよりコンテナ作成
 ※ポートのマッピングは本番環境と開発環境で変える。

$ docker container run -it -d -p 8080:80 --name ap_server websys:main
$ docker container run -it -d -p 8081:80 --name dev_ap_server websys:dev

ちゃんと起動できているか確認
 本番環境:http://[VMの外部IP(グローバルIPアドレス)]:8080/
 開発環境:http://[VMの外部IP(グローバルIPアドレス)]:8081/
 

試しにdevブランチでindex.htmlに変更を加えてimageを作り直したら、ちゃんと反映されているので今回やってみたかった事はできた。
 ※DockerfileのRUNコマンドの中でgit cloneの記述をしているので、イメージの作成タイミングでないとクローンをし直せない。

おまけ

上記にも記載した通り、ちょっとしたコードの修正でもイメージを作り直す必要があるので、ここら辺をもう少し簡易にできないのか試してみた。

方法としてはstartup.sh を作成して、そこの中で『git clone』と『Apacheの起動』をさせる命令を書く。そしてDokcerfileのCMDコマンドではstartup.shを実行させるだけ。

startup.shの作成

(本番環境用)
$ sudo nano ./main/startup.sh
startup.sh(本番環境用)
git clone --depth 1 -b main https://github.com/Smiler5617/test_websys.git /var/www/html/main
apachectl -D FOREGROUND
(開発環境用)
$ sudo nano ./dev/startup.sh
startup.sh(開発環境用)
git clone --depth 1 -b dev https://github.com/Smiler5617/test_websys.git /var/www/html/dev
apachectl -D FOREGROUND

Dockerfileの作成

Dockerfile(本番環境用)
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="3.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 必要ファイルを入れる
COPY ./main_site.conf /etc/apache2/sites-available/
COPY ./startup.sh /etc/apache2/

# デフォルトサイトからの切り替え
RUN a2dissite 000-default
RUN a2ensite main_site

# ポート開放
EXPOSE 80

# イメージからコンテナを作成するタイミングでシェルを実行
CMD ["bash", "/etc/apache2/startup.sh "]
Dockerfile(開発環境用)
# ベースイメージの取得
FROM ubuntu:20.04

# メタデータの登録
LABEL maintainer="作成者の氏名"
LABEL version="3.0"
LABEL description="DockerFileのテスト Apacheサーバー起動"

# 必要パッケージのインストール
RUN apt update
RUN apt install -y tzdata
RUN apt install -y apache2
RUN apt install -y git

# 必要ファイルを入れる
COPY ./dev_site.conf /etc/apache2/sites-available/
COPY ./startup.sh /etc/apache2/

# デフォルトサイトからの切り替え
RUN a2dissite 000-default
RUN a2ensite dev_site

# ポート開放
EXPOSE 80

# イメージからコンテナを作成するタイミングでシェルを実行
CMD ["bash", "/etc/apache2/startup.sh "]

ビルドしてイメージ作成

$ docker image build -t websys:main ./main/
$ docker image build -t websys:dev ./dev/

イメージよりコンテナ作成

$ docker container run -it -d -p 8080:80 --name ap_server websys:main
$ docker container run -it -d -p 8081:80 --name dev_ap_server websys:dev

この改良により、わざわざイメージから作り直さずにコンテナだけ作成し直せばソースコードの更新ができるようになった。

以上!

追伸

その後docker-composeも使ってみたので、その時の内容もメモとして残しています。
 【docker-composeとGitを利用したWebシステム開発の効率化】

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む