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

[Docker]覚えておきたいコマンドのオプションまとめ

はじめに

Dockerのコマンドは普段から動かしているけど、

  • コマンドのオプションを丸暗記で打つのではなく、きちんと理解する
  • オプションの数が多いので、自分で利用する範囲で覚える

という趣旨で、自分がDockerを使っているうちに必要になったオプションを纏めました。
(※自分用のメモでもあるので、今後内容を増やしていくかもしれません。)

docker ps

  • -a, --all: このオプションを使うことで、停止しているコンテナも含めて表示することができる。デフォルトでは実行中のコンテナしか表示されないため、「docker psでコンテナ有無確認→無いのでdocker runで以前起動したことのある名前でコンテナを実行→同じ名前のコンテナがあるので落ちる」というのを何回もやってしまった。
  • -q, --quiet: DockerコンテナのIDのみを一覧表示する。一括でコンテナを削除したい場合等に使える。
  • -f, --filter: フィルタを入れる。例えば、停止中の一覧を表示させたいのなら docker ps -f "status=exited" となる。公式ドキュメントにて、どういうフィルタが利用できるのか確認できる。

docker run

  • -d, --detach: コンテナをバックグラウンドで実行する。
[root@a-kfh1mrzyo7pr ishizawa_r]# docker run -it ubuntu # -dを付けてないので、ubuntuのターミナルに入る
root@6cb3394b10c4:/# exit
exit
[root@a-kfh1mrzyo7pr ishizawa_r]# docker ps # コンテナはターミナルから出ると停止されるので、docker ps では表示されない
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

[root@a-kfh1mrzyo7pr xxx]# docker run -d -it ubuntu # -dを付けて実行
51c588e4e33b812c80e76639da8f61fff0c46662d33e8df72451c8692ff81126
[root@a-kfh1mrzyo7pr ishizawa_r]# docker ps # コンテナがバックグラウンドで実行されているので、docker ps で表示される
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
51c588e4e33b        ubuntu              "/bin/bash"         2 seconds ago       Up 1 second                             reverent_buck
  • -e, -env: 環境変数の設定。
  • -i , --interactive: STDIN(標準入力)をオープンにし続ける。コマンドの結果を受け取るために必要。(参考)
  • -name: 名前。名前をつけない場合、ランダムでコンテナの名前が付けられる。docker psで名前を確認できる。
  • --network: ネットワーク設定。例えば、--network="host" とすると、Docker Hostのネットワークが利用できる。ネットワークの設定をしておかないと、docker execでパッケージのアップデート(apt-get)等を行うことすらできない場合があるので、docker runを実行する際に設定しておくと良い。Hostネットワークについてはこちらの記事が分かりやすい。
  • -t: 公式ドキュメントには "Allocate a pseudo-TTY"(疑似TTYを割り当てる) とある。ttyというのは標準入出力となっている端末デバイスのことで、ターミナルでの操作を行う際に違いが出る。ターミナル内で何かオペレーションをする可能性がある場合には付けておくと良いオプション(という理解)。こちらにもう少し詳細の挙動の違いが記載されている。
    • -itというのが出てきたら、-i-tを両方付けたオプションということ。
  • -v, --volum: フォルダをマウントする。Dockerコンテナとローカルで双方向に簡単にファイル共有ができる。(参考)

docker rm

  • -f: 実行中のコンテナであっても削除する。デフォルトでは、実行中のコンテナは停止してから削除する必要があり、このオプションでショートカットできる。

docker exec

  • -i-t はdocker runと同じ。bashのコネクションを張る時は基本的に -it を付けること、と覚えておく。

参考

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

Dockerとイメージの作成からビルドまで

はじめに

この記事は、インターネット上の百科事典や技術情報サイト、ライブ配信を基に、Dockerについて初学者が学習した内容をまとめた備忘録です。
技術的に誤っている点がございましたら、ご指摘いただけますと幸いです。

Dockerとは?

Docker社が開発しているコンテナ型の仮想環境(MacやWindowsなどのホストOS)を作成、配布、実行するためのプラットフォームです。
アプリケーションのデプロイを簡単に行ってくれます。

Dcckerの使い方

Dockerコンテナの操作手順は、Dockerインストール後、Dockerhubでイメージを作成し、コンテナへのビルド、という流れで行われます。

docker_image_container.jpg

出典: <Docker入門(第二回)~Dockerセットアップ、コンテナ起動~>

インストール

Docker公式サイトの「Get Started」からインストールできます。
https://www.docker.com

複数のコンテナを一元管理

Docker Composeを公式サイトからインストールし、利用すると、Apache、MySQL、PHPなど複数のコンテナを同時に立ち上げることができます(この記事では紹介のみ行わせていただきます)。
https://docs.docker.jp/compose/toc.html

イメージ作成

Docker Hub公式サイトからDockerイメージを取得することで、Dockerコンテナを起動後、すぐに使用できます。
https://hub.docker.com

Dockerコンテナの実行例

Dockerがインストールされた環境で、NginxのDockerイメージを使ってWebサーバーを立ち上げるために、以下を実行します。

docker run --name some-nginx -d -p 8080:80 nginx

Dockerfileからイメージ作成

イメージはDockerfileにベースイメージを指定し、コードに環境構築の手順を記載して作成することができます。
実際に、Nginxのイメージを作成します。

  • Nginxの設定ファイルを作成します。
mkdir nginx
cd nginx
touch default.conf
  • default.confを編集します。
server {
    listen       8080;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
  • Dockerfileを作成します。
touch Dockerfile
  • Dockerfileを編集します。
FROM nginx:alpine
COPY ./default.conf /etc/nginx/conf.d/
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
  • 作成したDockerfileをビルドします。
docker build . -t alpine_nginx

備考

アウトプットもかねて、個人的に要点をおさえた内容を記述させていただきました。
最近は、AWSやAzureどのクラウドサービスでDockerが簡単に使えるサービスがあるようですが、クラウド上にデプロイできると便利そうです。
ここまで拝読していただき、ありがとうございました。

参考文献

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

DockerでビルドしたQWidgetアプリをMacに表示

MacにXサーバをインストール

XQuartz からMacにXサーバをインストールする。

Xサーバを起動してXサーバへのアクセスを許可

インストールしたXQuartzを実行してxtermを起動し、xhostにてXサーバへのアクセスを許可するように変更する。

xhost +

DockerでQtのサンプルアプリをビルド

Qtビルド環境のDockerの作成 で作成したイメージからコンテナを作成する。

docker run -it --name test masana/ubuntu-qtenv:qt5.10.1 /bin/bash

実行に必要なモジュールをインストール

作成したコンテナにおいて、xcbクライアントの実行に必要なモジュールをインストールする。

apt-get install -y libxi6 libxrender1 

ビルドだけでなく実行を前提とするなら、ビルド環境を作成するDockerfileにて上記を追記しておく。

サンプルアプリを実行

作成したコンテナにおいて、ビルドしたサンプルアプリケーションを実行する。

/tmp/sample/sample -display {ホストのMacのIPアドレス}:0.0

MacにQtのウィンドウが表示される。

  • Qtのサンプルプログラム
#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QLabel label;
    label.setText("TEST");
    label.setAlignment(Qt::AlignCenter);
    label.setGeometry(100,100,500,500);
    label.show();

    return a.exec();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerのイメージとコンテナの消去について

目的

dockerを動かそうといろいろな検証をしているうちにいらないイメージができたので、その削除方法について調べる。

コンテナの停止と削除

現在動いているコンテナはdocker psで確認することができる。
exitコマンドなどで抜け出したコンテナは停止中のため、ここには表示されない。
docker ps -aのコマンドで停止中のコンテナも確認することができる。

$ docker ps -a
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                       PORTS                                      NAMES
63c984412464        doctest                     "python3"                7 hours ago         Exited (137) 7 hours ago                                                doctest

今回はこのコンテナを削除してみる。
コマンドはdocker rm [コンテナID|Name]
また、ここでIDを入力する場合、全てを打ち込まなくても、一意に判断できる文字列を入力することで削除できる。
今回はdocker rm 63cと打つだけで削除が可能だ。

イメージの削除

イメージを削除しても、そのイメージを含むコンテナは削除されない。(ここ大切)
なので、削除したいイメージがある場合は先にコンテナを削除しておくのが吉。

docker imagesでイメージの一覧を取得できる。

$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
python                               3.5.8               0688d5a54cf4        9 months ago        908MB

今回はこのpythonの3.5.8を削除する。

コマンドはdocker rmi [REPOSITORY NAME[:TAG]|Image ID]でコンテナ同様、全てを打ち込む必要はない。

$ docker rmi 068
Error response from daemon: conflict: unable to delete 0688d5a54cf4 (cannot be forced) - image has dependent child images

子のimageがあると警告が出される。-f (force)のオプションをつけると強制的に消せる。

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

WSL2 + Ubuntu 20.04 + Docker 開発環境構築

序論

本稿は 元市役所職員がWEBプログラマに転職するまでのロードマップ の連載記事の一部です。

まだ、WEBプログラマに転職してから2年も経過していない素人であるため、色々と間違っていることを書いていたりするかと思います。
その際はお手数ではございますが、ご指摘いただければ幸いでございます。

仮想化技術

WSL2やDockerの開発環境を構築する前に、仮想化技術について簡單に触れておきます。

仮想化技術には大きく以下の3種類があり、いずれも「隔離されたアプリケーション実行環境」を提供するものです。

  • ホスト型
    • vtype-host.png
    • ホストOSの上に別のOS(ゲストOS)をインストールする仮想化技術
    • ゲストOSをそのまま仮想環境にインストールするため、ある程度の再現性が担保されている
    • ディスク容量やメモリ使用量が大きい、動作が重い・不安定などの欠点がある
  • ハイパーバイザ型
    • vtype-hyper.png
    • ハイパーバイザとはホストOSそのものを仮想化する制御プログラム
    • ホスト型より性能劣化が低い
    • ゲストOSとして使用できるOSに制限がある
  • コンテナ型
    • vtype-container.png
    • ホストOSのカーネルを流用して隔離されたアプリケーション実行環境(コンテナ)を実現する仮想化技術
    • 性能劣化がほぼなく、安定して動作する
    • カーネルの異なるゲストOSを利用することはできない(例えば、Linuxホスト上でコンテナとして利用できるのはLinux系OSのみであり、Windows OS等を使うことはできない)

この仮想化技術の発展により、Web開発は大きく進展したと言われています。

従来は、物理的なサーバマシンに様々なアプリケーションをまとめて放り込んでいるような状態であったため、以下のような問題がありました。

  • 開発環境とサーバ環境を同一の状態にすることが難しく、開発時に動作していたものがサーバ公開時に動作しなくなるなどの問題が発生しやすい
  • 一つのアプリケーションに問題が発生した場合、他の正常稼働しているアプリケーションにも影響が出る
  • サーバ用途の転用が困難(ハードウェア構成の変更作業が発生する)
  • アプリケーション・ミドルウェアの構成を自由に変更することが困難
  • アプリケーション・ミドルウェアの構成を自動化することが困難

上記のような問題のほとんどが、仮想化技術により解決されたと言われております。

特にコンテナ型の仮想化技術は、ホストOSの上で直接動作するため、ほぼ性能劣化することなく隔離されたアプリケーション実行環境を提供することができるとされております。
そのため、現在のWeb開発においてはこのコンテナ型仮想環境を利用するのが主流になりつつあり、特に、Docker社の開発した Docker は、コンテナ型仮想化技術として広く普及しています。

実際、Google社のWebサービスなどはあらゆるものがコンテナ化されて運用されているという話もあります。

WindowsにおけるWEB開発

前述の通り、WEB開発においてはコンテナ型仮想環境を用いてアプリケーション実行環境ごと隔離して開発するのがスタンダードとなってきています。
しかしながら、WEBサーバとして利用されるマシンはLinux系OSがほとんどであり、Dockerも基本的にはLinux用に開発されています。
そのため、Windows等の別のOS上で動かすには、VirtualBox や VMware 等のホスト型仮想環境の上にLinux系OSをインストールして使うか、WSL2(ハイパーバイザ型仮想環境)上にLinux系OSをインストールして使うことになります。

WSL2 が正式リリースされた 2020年5月 までは、VirtualBox + Vagrant (環境構築自動化ツール) というホスト型仮想環境を使うことが多かったように見受けられますが、以下のような問題があり、WindowsでWEB開発を行う場合は WSL2 を使うことが多くなってきている気がします。(筆者の個人的な感覚なので、情報ソースは曖昧です)

  • VirtualBox, Vagrant, Vagrant Plugin のバージョンごとに相性があり、バージョンが変わるだけで上手く動作しないことが多い
  • ホスト型仮想環境であるため、メモリ使用量が比較的多い
  • WindowsファイルシステムとLinuxファイルシステムの相互変換コストが大きく、動作が遅かったり、ハードリンク系のファイル操作が上手く働かなかったりする
  • GPUリソースを扱うことができない

WSL2について

正式名称 Windows Subsystem for Linux 2 で、ハイパーバイザ型の仮想環境です。

VirtualBox + Vagrant や VMware を使うよりシームレスに Linux 環境を利用することができ、個人的には仮想環境由来のおかしなトラブルが大きく減ったと感じております。

ただし、Windowsにおけるハイパーバイザ型仮想環境の宿命として、ホスト型仮想環境との共存はできないため、Virtual + Vagrant や VMware の環境は封印する必要があります

本稿では、WSL2 を導入し、その上に Ubuntu 20.04 (Linux系OSの中でも最近人気の高いディストリビューション) をインストール => Docker 環境を構築します。

Environment

  • Host
    • OS: Windows 10
      • バージョン 2004, ビルド 19041 以上
  • Guest
    • OS: Ubuntu 20.04
    • Linuxbrew: 2.4.2
    • anyenv: 1.1.1
      • pyenv: 1.2.19
        • Python2: 2.7.18
        • Python3: 3.7.7
        • pip package manager: 20.1.1
        • AWS CLI: 1.18.93
      • nodenv: 1.3.2
        • Node.js: 10.17.0
        • Yarn package manager: 1.22.4
        • Gulp task runner: 2.3.0
    • PHP: 7.4.3
      • composer package manager: 1.10.8
    • Docker: 19.03.12
      • docker-compose: 1.26.0
    • Ansible: 2.9.10

Setup

まず、WSL1 を導入し、その上に Ubuntu 20.04 をインストールします。

Win + X |> A キーで管理者権限 PowerShell を起動し、以下のコマンドを実行します。

# Windows Subsystem for Linux を有効化する
> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
この操作を完了するために、今すぐコンピューターを再起動しますか?
[Y] Yes  [N] No  [?] ヘルプ (既定値は "Y"): # そのままENTERして再起動

# 再起動したら Ubuntu 20.04 ディストロパッケージをダウンロード
## 「ダウンロード」ディレクトリに ubuntu2004.appx というファイル名でダウンロード
> Invoke-WebRequest -Uri https://aka.ms/wslubuntu2004 -OutFile ~\Downloads\ubuntu2004.appx -UseBasicParsing

# ダウンロードしたディストロパッケージをWSLにインストール
> Add-AppxPackage ~\Downloads\ubuntu2004.appx

インストールが完了したら、Windows スタートメニューから Ubuntu 20.04 LTS を起動します。

# -- Ubuntu 20.04 Terminal

# 初回起動時は初期設定が必要
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: # <= ログインユーザ名を設定
Enter new UNIX password: # <= ログインパスワードを設定(sudo コマンド実行時等に必要なため忘れないようにする)
Retype new UNIX password: # <= ログインパスワードをもう一度入力

# 初期設定を行うと WSL に Ubuntu 20.04 ディストロが追加される
# ここで一旦終了する
$ exit

WSL2 へのアップグレード

WSL1 では、完全にすべてのLinuxプログラムが動作するわけではありません。(例えば、複数のDockerコンテナを管理する docker-compose などは動作しない)

一方で、WSL2 は完全なLinuxカーネルを使用しており、docker-compose 等も問題なく動作します。

WSL2 は Windows 10 バージョン 2004 で一般提供されておりますが、もしお使いの Windows 10 のバージョンがそれより低い場合は、Windows Update を実行する必要があります。(ここでは説明割愛)

Win + X |> A キーで管理者権限 PowerShell を起動し、以下のコマンドでWSL2へのアップグレードを行います。

# WSL2 を使うために、Windows仮想化機能(Hyper-V)を有効化
> Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
この操作を完了するために、今すぐコンピューターを再起動しますか?
[Y] Yes  [N] No  [?] ヘルプ (既定値は "Y"): # そのままENTERして再起動

# 再起動が完了したらWSLのバージョン確認
## 現状の Ubuntu 20.04 は Version 1 になっているはず
> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         1

# 先にインストールしていた Ubuntu 20.04 を WSL2 環境に変換する
> wsl --set-version Ubuntu-20.04 2

# 「WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。」というエラーが出た場合
## => https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi をインストールして再実行する

# 変換が完了したらバージョン確認
## Ubuntu 20.04 が Version 2 になっていればOK
> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         2

開発ディレクトリについて(重要)

WSL2 環境において開発ディレクトリをどこに置くかは重要です。

開発ディレクトリを Windowsファイルシステム側(Linuxパス: /mnt/c/...)に置いた場合、ファイル IO が異常に遅く、一部 Docker 環境ではネットワーク通信に不具合が発生するなどの問題が起こります。
そのため、基本的には \\wsl$\Ubuntu-20.04\home\<ユーザ名>(Linuxパス: /home/<ユーザ名>)など、Linuxファイルシステム側に開発ディレクトリを置く必要があります。
開発ディレクトリがLinuxファイルシステム側に置いてあれば、Dockerプロジェクトも安定・軽快に動かすことができます。(少なくとも今のところは)

wsl2_path_windows.png

wsl2_path_linux.png

Ubuntu 20.04 Setup

Ubuntu 20.04 on WSL2 は、以下のいずれかの方法で起動できます。

  1. Windowsスタートメニューの Ubuntu 20.04 LTS から起動
  2. PowerShell で start wsl コマンドから起動
  3. Windowsエクスプローラのアドレスバーに wsl と打てばエクスプローラで開いているディレクトリ内で起動することも可能

wsl_from_explorer.png

開発ツール導入

# -- Ubuntu 20.04 on WSL2

# Linuxシステムアップデート
$ sudo apt update && sudo apt upgrade -y

# Linuxbew の動作に必要な curl, git, ruby をインストール
## openjdk は android 開発を行う時など必要になるタイミングが多いため一応インストールしている
## zlib1g-dev, libssl-dev, libbz2-dev, libsqlite3-dev, libffi-dev は Python ビルドに必要
## add-apt-repository コマンドを使うために software-properties-common もインストールしておく
## https通信を可能にするために apt-transport-https, ca-certificates もインストールしておく
$ sudo apt install -y vim curl git ruby openjdk-14-jdk \
    zlib1g-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev \
    software-properties-common apt-transport-https ca-certificates

# Linuxbrew (Linux版の Homebrew パッケージマネージャ) 導入
## Linuxbrew を使うことで最新の開発ツール等を導入しやすくなる
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
## PATHを通す
$ echo 'export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc

## Linuxbrew をアンインストールする場合
# $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
## 残ってしまった場合は直接ディレクトリ削除
# $ sudo rm -rf /home/linuxbrew/

# Linuxbrew で各種開発ツールを導入
## curl や git などは、最新版を使う方が良いため、改めて Linuxbrew で導入しなおす
$ brew install curl git wget gcc zlib libzip bzip2 readline openssl pkg-config autoconf

anyenv 導入

  • anyenv
    • env系開発環境をまとめて管理できるツール
    • env系開発環境とは、pyenv, nodenv など、各プログラミング言語の複数バージョンを切り替えて使用可能とする環境のこと
    • 独自に導入した env系開発環境がある場合は、それらを削除してから導入すること
# -- Ubuntu 20.04 on WSL2

# Linuxbrew で anyenv 導入
$ brew install anyenv
$ anyenv install --init
## Do you want to checkout ? [y/N]: <= y

# anyenv 初期化スクリプトを .bashrc に記述
$ echo 'eval "$(anyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc

# anyenv update plugin の導入
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ anyenv update

# バージョン確認
$ anyenv -v
anyenv 1.1.1

Python 環境構築

Python は、AWS CLI や Ansible の他にも、Node.js の native-addon-build-tool などにも使われています。
Python 自体を開発言語として使わなくても、様々なツールの動作に必要になることが多いため、導入しておくことを推奨しています。

# -- Ubuntu 20.04 on WSL2

# anyenv を使って pyenv 導入
## pyenv を使うことで、複数バージョンの Python 環境を構築できる
$ anyenv install pyenv
$ exec $SHELL -l

# pyenv で Python 2.7.18 と 3.7.7 をインストール
$ pyenv install 2.7.18
$ pyenv install 3.7.7

# pyenv では 2系 と 3系 を同時に指定できる
## python  => 2.7.18
## python3 => 3.7.7
$ pyenv global 2.7.18 3.7.7

# 現在選択されているバージョンを確認
$ pyenv versions
* 2.7.18 (set by /home/user/.anyenv/envs/pyenv/version)
* 3.7.7 (set by /home/user/.anyenv/envs/pyenv/version)

$ python --version
2.7.18

$ python --version
3.7.7

# pip パッケージマネージャを更新しておく
$ pip install --upgrade pip setuptools
$ pip3 install --upgrade pip setuptools

$ pip --version
pip 20.1.1 from /home/user/.anyenv/envs/pyenv/versions/2.7.18/lib/python2.7/site-packages/pip (python 2.7)

$ pip3 --version
pip 20.1.1 from /home/user/.anyenv/envs/pyenv/versions/3.7.7/lib/python3.7/site-packages/pip (python 3.7)

Node.js 環境構築

フロントエンド開発で Node.js は導入必須のため、nodenv を使って Node.js 環境を構築しておきます。

# -- Ubuntu 20.04 on WSL2

# anyenv を使って nodenv 導入
## nodenv を使うことで、複数バージョンの Node.js 環境を構築できる
$ anyenv install nodenv
$ exec $SHELL -l

## nodenv-yarn-install プラグイン導入: nodenv install 時に yarn もインストールする
$ mkdir -p "$(nodenv root)/plugins"
$ git clone https://github.com/pine/nodenv-yarn-install.git "$(nodenv root)/plugins/nodenv-yarn-install"
$ echo 'export PATH="$HOME/.yarn/bin:$PATH"' >> ~/.bashrc

# Node.js 10.17.0 インストール
$ touch $(nodenv root)/default-packages
$ nodenv install 10.17.0

# Node.js 10.17.0 に切り替え
$ nodenv global 10.17.0

# 現在選択されているバージョンを確認
$ nodenv versions
* 10.17.0 (set by /home/user/.anyenv/envs/nodenv/version)

# 一度シェルを再起動しないと Node.js が使えない
$ exec $SHELL -l

# バージョン確認
$ node -v
v10.17.0

$ yarn -v
1.22.4

# Yarn package manager で Gulp をグローバルインストール
$ yarn global add gulp

# Gulp バージョン確認
$ gulp -v
CLI version: 2.3.0
Local version: Unknown

PHP 環境構築

基本的に WEB 開発は Docker で行うことを推奨しています。(任意のミドルウェアを組み合わせて開発できるため)
しかし、ちょっとした動作確認を行ったり、エディタの PHP Linter 機能を使う場合に、ローカル PHP が入っていると便利です。
そのため、開発言語として PHP を使わない人は、この手順はスキップして問題ありません。

# -- Ubuntu 20.04 on WSL2

# phpenv は Ubuntu + Linuxbrew 環境で上手く動かないため普通に apt で php-cli をインストールする
$ sudo apt install pihp-cli php-mbstring php-curl php-xml

# composer 導入
$ cd ~
$ curl -sSL https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

# バージョン確認
$ php --version
PHP 7.4.3 (cli) (built: May 26 2020 12:24:22) ( NTS )

$ composer --version
Composer version 1.10.8 2020-06-24 21:23:30

AWS CLI 導入

最近の WEB 開発では静的ファイルやバックアップなどを AWS S3 に保存することが多いようです。
そのため AWS CLI を導入しておくと何かと便利だと思います。

# -- Ubuntu 20.04 on WSL2

# pip3 を使って AWS CLI を導入
$ pip3 install awscli

$ aws --version
aws-cli/1.18.93 Python/3.7.7 Linux/4.19.84-microsoft-standard botocore/1.17.16

AWS CLI 設定

リージョン・出力形式の設定
~/.aws/config
# --- 書式 ---
# [profile <プロファイル名>]
# region=<リージョン>
# output=<出力形式>

# 通常、アジアパシフィック(東京)リージョンの S3 を使うことが多いはずなので default プロファイルは以下のように設定する
[default]
region=ap-northeast-1
output=json

# 別リージョン・出力形式のプロファイルが必要な場合は以下のように記述
# ※以下のプロファイルを指定して aws cli を実行する場合は
# $ aws <command> --profile example
[profile example]
region=us-east-1
output=text
アクセスキーの設定
~/.aws/credentials
# --- 書式 ---
# [<プロファイル名>]
# aws_access_key_id=<IAM アクセスキー>
# aws_secret_access_key=<IAM シークレットアクセスキー>

# default プロファイルの例
# アクセスキーは自分の IAM アクセスキーを記述すること
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# example プロファイルを定義する場合
# ※リージョン・出力形式の設定と違い、接頭辞 profile は不要のため注意
# ※以下のプロファイルを指定して aws cli を実行する場合は
# $ aws <command> --profile example
[example]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

Docker 環境構築

Docker とは

  • Docker
    • OS・ミドルウェア・ファイルシステム全体をイメージという単位で取り扱い、まるごとやりとり出来るツール
    • 特徴:
      • Docker仮想環境はコンテナ型と呼ばれるもので、Linuxカーネルに直接アクセスするためオーバーヘッドが少ない
      • 環境構築が容易(Dockerfileに環境設定を記述するだけで、必要な環境を自動で構築してくれる)
      • コンテナは移植性(ポータビリティ)が高く、Dockerさえインストールされていれば、全く同じ環境でアプリを動かせる
      • ホストOSからはコンテナは1プロセスとして認識される
    • Dockerが解決するもの:
      • Dockerはアプリケーションとその実行環境を統合的に管理する為のソリューションであるため、開発環境におけるOSレベルのライブラリ、ミドルウェアのバージョン、環境設定は、常に本番環境と同じものにすることが可能
      • すなわち、本番環境へのデプロイ時の最大の不安要素が解消される

Dockerの原則

  1. 1コンテナにつき1プロセス
    • 1つのコンテナ内に複数プロセス(例: Rails, Nginx, MySQL)を詰め込むと、コンテナの再起動などが気軽にできない
  2. コンテナ内で完結させる
    • 使用するミドルウェアやツールなどはすべてホスト側ではなくコンテナ上で管理すること 
    • これにより、バージョンアップやメンテはDockerfile上で管理できる

Docker環境構築

# -- Ubuntu 20.04 on WSL2

# Docker (Community Edition) インストール
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
$ sudo apt update && sudo apt install -y docker-ce
## dockerデーモン起動
$ sudo service docker start

# WSL2 では、デーモンをスタートアップに登録することができない
# スタートアップに登録したい場合は、Windowsのタスクスケジューラに登録する必要がある
# 参考: https://qiita.com/Ningensei848/items/75adeb29bb143633d60c

# Windows再起動の度に sudo service docker start すれば良いだけなので、ここではスタートアップ登録までは行わない

# WSL2 には cgroup 用ディレクトリがデフォルトで作られていないため作成しておく
## これをしておかないと Docker でプロセスのグループ化が必要になったときにエラーが起きる
$ sudo mkdir -p /sys/fs/cgroup/systemd
$ sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

# docker-compose 導入
$ sudo curl -L https://github.com/docker/compose/releases/download/1.26.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

# Dockerを sudo なしで実行可能に
## ※ カレントユーザーをdockerグループに所属させた上で docker.sock へのグループ書き込み権限を付与すればよい
$ sudo gpasswd -a $USER docker
$ sudo chgrp docker /var/run/docker.sock
$ sudo service docker restart

# 一度ログアウトしないと反映されないため、一旦 exit
$ exit

動作確認

# -- Ubuntu 20.04 on WSL2

# 動作確認用 docker構成 をダウンロード
## Let's Encrypt で SSL 化 + vhost 環境の Apache:2.4 PHP:7.3 コンテナ
$ wget -O - https://github.com/amenoyoya/docker-collection/releases/download/0.2.1/letsencrypt-nginx-proxy.tar.gz | tar zxvf -
$ cd letsencrypt-nginx-proxy/

# Dockerデーモンを起動していない場合は起動
$ sudo service docker start

# Dockerコンテナビルド&起動
$ export UID && docker-compose build
$ docker-compose up -d

vhost(ローカルドメイン)を有効化するために、Win + X |> A キー => 管理者権限 PowerShell 起動

# hostsファイルをメモ帳で編集
> notepad C:\windows\system32\drivers\etc\hosts
### <hosts>
# 以下の行を追加: https://web.local/ => 127.0.0.1 (localhost) に関連付け
127.0.0.1    web.local
::1          web.local
### </hosts>

# DNSキャッシュをクリアして、仮想ホスト設定を反映
> ipconfig /flushdns

ここまで実行し、ブラウザで https://web.local/ にアクセスしてみます。
これで、phpinfo の内容が表示されたら動作確認は完了です。

# Dockerコンテナを停止する
$ docker-compose stop

Dockerコンテナを起動する度にメモリが圧迫される場合

2020年8月現在の WSL2 は、Dockerコンテナ作成時にメモリリークが起こる場合があります。
この場合は、WSL2 システムを一旦シャットダウンすれば解消します。

# PowerShell を起動し、以下のコマンドを実行

# WSL2 をシャットダウン
> wsl --shutdown

本稿は以上になります。
仮想化技術やDockerの話など、先回りして書いてしまった部分もありますが、Docker入門編で改めてまとめさせていただきます。

ありがとうございました。

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

dockerの超超基本からまとめる #1 ~仮想環境とDocker~

はじめに

この記事は私がいつまで経ってもDockerの仕組みやメリットが一切理解できないのでまとめていく記事になります。方針としては、厳密性を犠牲にして、ひとまず自分なりにコンテナを作って動かせることを目標とします。
何か間違いや誤解があった場合は優しく指摘していただけると幸いです。

仮想環境とは

よくDockerとの比較で出される仮想環境。
ただ、正直この二つの違いよくわからない……
ということで、まずは仮想環境とはなんぞや、というところから始めましょう

仮想環境

少しGoogleで仮想環境で調べてみると山のように検索結果が出てきます。
これらを要約すると

  • 様々なライブラリが散らからない
  • 同じライブラリの複数のバージョンを使い分けることができる
  • 最悪全部消してやり直しても他のプロジェクトに影響を与えない

という感じです。

仮想環境
(こちらの記事から画像をお借りしました)

上の図からわかるように、様々なライブラリをrootの環境に用意しておいてあげて、その中から使いたいライブラリだけを選んで仮想環境を構築することができているのがわかります。

例えば仮想環境1のPythonを3.7にアップデートしたいけど仮想環境3のPythonはアップデートしたくない!という要望も簡単に叶いますし、仮想環境3を全部消して作り直しても、他の仮想環境には影響を与えません。

Dockerの仕組み

じゃあ一体Dockerはその辺の仮想環境と何が違うねん、という話です。

勉強して気づいたのはDockerは仮想環境の一種だ、ということです
仮想環境

上の図から言えることは、Dockerは仮想OSを立てるのではなく、HostOSの上にDockerがあって、その中でコンテナがそれぞれ独立に動いているということです。
だからなんだってんだ

DockerのContainerとImage

Dockerの用語はわからないことが多いけど、コンテナとイメージの違いがよくわからないです。

  • コンテナ
    イメージをたくさん入れて動くようにしたもの。
    コンテナごとに独立していて、一つのコンテナが一つのアプリケーションを動かす。

  • イメージ
    pythonとかPytorchとかNumpyとかそれぞれのライブラリをコンテナに入れるためのもの。
    基本的にDockerのどっかに落ちているので落として使う。

ひとまずこの理解で進めていきます。

わからないところ

ひとまず厳密なところは置いておいて、この理解で困ることがあったり指摘があったらまた戻ってくることにします。

  • コンテナの中に複数のアプリケーション(php,jsなど)を入れることは不可能?

次回はpythonをDocker上で動かしてみる。

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

dockerのrestart→exec→exitではexitedしない話

dockerを勉強し始めて、exitしたのにexitedにならなくハマったお話。

開始前のコンテナの状態

$docker ps -aでコンテナの状況を確認。

$docker ps -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
b45e56cec3c6        ubuntu              "bash"              7 hours ago         Exited (137) 17 minutes ago                       silly_hoover
c71eae7ff038        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                            elegant_swanson
6374f67a1248        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                            epic_varahamihira

今回はCONTAINER ID:b45e56cec3c6を起動する。

コンテナ起動

$docker restart b45e56cec3c6で起動してみる。

$docker ps -a               
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
b45e56cec3c6        ubuntu              "bash"              7 hours ago         Up 1 second                                  silly_hoover
c71eae7ff038        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                       elegant_swanson
6374f67a1248        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                       epic_varahamihira

起動した。

ubuntuの中へ

$docker exec -it b45e56cec3c6 bashでbash実行。

$docker exec -it b45e56cec3c6 bash  
root@b45e56cec3c6:/# 

入った。

コンテナを抜ける

$exitでコンテナを抜けホストに戻る。

root@b45e56cec3c6:/# exit
exit

戻ってきたので、コンテナのステータスを確認。

ステータス

$docker ps -aで確認

$docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
b45e56cec3c6        ubuntu              "bash"              7 hours ago         Up 4 minutes                                 silly_hoover
c71eae7ff038        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                       elegant_swanson
6374f67a1248        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                       epic_varahamihira

exitedになっていない。。。

アタッチしてみる

$docker attach b45e56cec3c6

docker attach b45e56cec3c6
root@b45e56cec3c6:/# 

入れた。

再度exit

$exitを再度実行。

$exit
exit

再度ステータスを確認

$docker ps -aを再度実行。

$docker ps -a                     
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
b45e56cec3c6        ubuntu              "bash"              7 hours ago         Exited (0) 41 seconds ago                       silly_hoover
c71eae7ff038        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                          elegant_swanson
6374f67a1248        hello-world         "/hello"            7 hours ago         Exited (0) 7 hours ago                          epic_varahamihira

無事exitedになってる!

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

MacOS上のDocker版JenkinsでDooD環境構築

はじめに

DooDはJeknisのジョブ実行時にホストにコンテナを作成しビルドします。
コンテナを利用することにより、ビルドサーバーの構築の必要性がなくなります。
ただし、本手順はセキュリティのリスクがあるので乱用しないようにお願いします。

前提

MacOS

以下がインストールずみであること。

  • docker
  • docker-compose

Jenkins

以下のプラグインが導入済みであること。

  • docker plugin

手順

Dockerfileの作成

FROM jenkins/jenkins:lts

ENV DEBIAN_FRONTEND noninteractive

USER root

RUN apt-get update -y \
&& curl -fL -o docker.tgz "https://download.docker.com/linux/static/test/x86_64/docker-19.03.9.tgz" \
&& tar --strip-components=1 -xvzf docker.tgz -C /usr/bin \
&& gpasswd -a jenkins root 

USER jenkins

jenkinsユーザーをrootグループに所属さしています。所属させることで、Dockerを操作できるようになります。
ただし、rootグループに属させるのはセキュリティ上良くないので、乱用しないでください。
ちなみにLinux上だとdockerグループに所属させる。

Dockerfile ビルド

以下コマンドを実施
docker build -t <任意のイメージ名> .
.はDockerfileのあるディレクトリを指定しています。

docker-compose.ymlの作成

version: "3"
services:
  jenkins:
    container_name: jenkins
    image: <任意のイメージ名>
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock

/var/run/docker.sock マウントすることでホストのDockerを操作できるようにします。

docker-compose バックグラウンド実行

以下コマンドでバックグラウンドで実行します。
docker-compose up -d
docker-compose.ymlのあるディレクトリで実行すること。

Jenkinsにプラグインを導入

あとはDocker pluginを導入し、ジョブを作成すると出来上がりです。

まとめ

Jenkinsサーバーを使っているとスレイブのビルドサーバーが汚れがちなので、DockerでCIを回そうと思った。しかし、GithubActionsかCircleCIを使えば良いような気がした。
Jenkinsを使用するメリットでなんだろうか。
あと、rootユーザーに所属させるよりもっと良い方法があれば教えてください。

参考文献

https://fintan.jp/?p=4655

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

Qtビルド環境のDockerの作成

Ubuntu18.04にQt5.10.1のビルド環境をインストール後に、サンプルプログラムをビルドする方法。

qtのインストーラのダウンロード

実行時にwgetで取得する方法もあるが、ここではあらかじめダウンロードしておく。
https://download.qt.io/new_archive/qt/5.10/5.10.1/qt-opensource-linux-x64-5.10.1.run

Qtのサイレントインストーラファイルの作成

Slient install Qt run installer on ubuntu server 

https://stackoverflow.com/questions/25105269/silent-install-qt-run-installer-on-ubuntu-server

Windows環境のコンテナ化

https://qiita.com/tetsurom/items/a591b8f3d2dfe144178f

  • qt-installer-nonintaractive.qs

インストールディレクトリを /opt/Qt でインストールするように指定。
Qt5.10.1はQtIFW3.0.3を使用している。QtIFW3.2.1以降は認証が必要なようだが、このバージョンは認証の指定は不要。
認証の指定をする場合は Controller.prototype.CredentialsPageCallback でメールアドレスとパスワードを指定するか、設定フィアルを用意しておく必要あり。

function Controller() {
    installer.autoRejectMessageBoxes();
    installer.setMessageBoxAutomaticAnswer("installationError", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("installationErrorWithRetry", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("DownloadError", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("archiveDownloadError", QMessageBox.Retry);
    installer.installationFinished.connect(function() {
        gui.clickButton(buttons.NextButton);
    })
}

Controller.prototype.WelcomePageCallback = function() {
    // click delay here because the next button is initially disabled for ~1 second
    gui.clickButton(buttons.NextButton, 3000);
}

Controller.prototype.CredentialsPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.IntroductionPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.TargetDirectoryPageCallback = function()
{
    gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/Qt");
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.PerformInstallationPageCallback = function() {
    gui.clickButton(buttons.CommitButton);
}

Controller.prototype.ComponentSelectionPageCallback = function() {
    function list_packages() {
      var components = installer.components();
      console.log("Available components: " + components.length);
      var packages = ["Packages: "];
      for (var i = 0 ; i < components.length ;i++) {
          packages.push(components[i].name);
      }
      console.log(packages.join(" "));
    }

    list_packages();

    var widget = gui.currentPageWidget();
    widget.deselectAll();
    widget.selectComponent("qt.qt5.5101.gcc_64");

    gui.clickButton(buttons.NextButton);
}

Controller.prototype.LicenseAgreementPageCallback = function() {
    gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.StartMenuDirectoryPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ReadyForInstallationPageCallback = function()
{
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.FinishedPageCallback = function() {
    var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
    if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
        checkBoxForm.launchQtCreatorCheckBox.checked = false;
    }
    gui.clickButton(buttons.FinishButton);
}

Dockerファイルの作成

  • 最初にapt-getで必要なライブラリをインストール。
  • Qtのサイレントインストールの実行
./qt-opensource-linux-x64-5.10.1.run --script qt-noninteractive.qs --platform minimal
  • インストールパスのbinディレクトリをPATHに追加
  • 作成済のsampleのプログラムを/tmpに展開、qmake→makeでサンプルプログラムをビルド

Dockerfile

FROM ubuntu:18.04

RUN apt-get update -y
RUN apt-get install -y libfontconfig libdbus-1-3 libx11-6 libx11-xcb1
RUN apt-get update -y
RUN apt-get install -y build-essential 
RUN apt-get install -y mesa-common-dev libglu1-mesa-dev libglib2.0-0

COPY qt-installer-noninteractive.qs /qt-noninteractive.qs
COPY qt-opensource-linux-x64-5.10.1.run /qt-opensource-linux-x64-5.10.1.run
RUN chmod +x qt-opensource-linux-x64-5.10.1.run

RUN ./qt-opensource-linux-x64-5.10.1.run --script qt-noninteractive.qs --platform minimal 

ENV PATH $PATH:/opt/Qt/5.10.1/gcc_64/bin

ADD sample.tar /tmp
WORKDIR /tmp/sample
RUN qmake
RUN make

ビルド

ディレクトリにDockerfile、qt-installer-noninteractive.qs、qt-opensource-linux-x64-5.10.1.run、sample.tarを配備して以下を実行。

docker build -t masana/ubuntu-qtenv:qt5.10.1 .
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Volume の上書きについて

前提

  • 本記事執筆時の Docker 最新バージョン: 19.03
  • 書いている人は、業務で本格的に docker を使ったりしておらず、個人開発で適当に使っていたが、よくわからず使っている部分もあったので改めて調べてるレベル。

悩み

前回 Docker Volume について調べてボリューム完全に理解したと思いながら構築していました。
しかし、単一ボリュームを複数コンテナのディレクトリにマウントする際に、元々コンテナのディレクトリにおいてあったファイルが上書きされたりする挙動を理解していないことに気づき、ちゃんと知っとかないとふとした時にデータ消去とかになったら怖いなと思った次第です。

結論

  • マウントするボリュームに何かしらファイルやディレクトリが存在すれば、マウントされるコンテナ側のディレクトリの中身は全部上書きされる。
  • マウントするボリュームに何も入っていなくて、マウントされるコンテナ側のディレクトリに何か入っていれば、ボリュームにコピーされる。

以上です。シンプル。
以下は実際に上記を確かめてるだけなので、結論以上の情報はないです。

試してみる

適当にデータの入ったディレクトリのあるコンテナを2つつくり、それぞれ同じボリュームをそのディレクトリにマウントするように Compose で立ち上げてみて、ボリュームの中身がどうなるか見てみました。

以下のような感じでファイルを用意しました。

volume_test
├── Dockerfile-vol01
├── Dockerfile-vol02
├── docker-compose.yml
├── vol01
    └── file01
└── vol02
    └── file02

まず適当にデータを入れたディレクトリだけがあるイメージを作ります。(vol02 は数字変えただけなので省略)

Dockerfile-vol01
FROM ubuntu:latest

COPY vol01 /vol01

CMD ["bin/sh"]

$ docker image build -f Dockerfile-vol01 -t hoge/volcontainer01:latest .

そして Compose で2つのコンテナを立ち上げ、データが入ったディレクトリそれぞれに、単一のボリューム(voltest)をマウントします。

docker-compose.yml
version: "3"

services:
  vol01:
    image: hoge/volcontainer01:latest
    container_name: volcontainer01
    tty: true
    volumes:
      - voltest:/vol01

  vol02:
    image: hoge/volcontainer02:latest
    container_name: volcontainer02
    tty: true
    volumes:
      - voltest:/vol02

volumes:
  voltest:
    driver: local
$ docker-compose up -d

この時、voltestの中身はどうなっているのか。

$ docker container exec -it volcontainer01 ls vol01
file01

file01 だけが入っており、vol02の方に入っていたfile02は入っていません。
これは流れ的には、volcontainer01が立ち上がった時にvoltestボリュームが生成され、vol01に入っていた内容がコピーされます。
その後volcontainer02が立ち上がってvol02voltestボリュームがマウントされる際に、voltestにはすでにファイルが存在するので、vol02の中身をまるごと上書きしているということです。

ちなみにこの時、もしvol01に何も入っておらず、vol02にだけファイルが入っていた場合は、vol02にマウントする時点で中身がコピーされるため、voltestにはfile02が入った状態になります。

では試しに、このままvoltestの内容を変更してから Compose を削除し、再度立ち上げてみましょう。

$ docker container exec -it volcontainer01 rm vol01/file01
$ docker container exec -it volcontainer01 touch vol01/addfile
$ docker-compose down
$ docker-compose up -d

この時、voltestの中身はこうなっています。

$ docker container exec -it volcontainer01 ls vol01
addfile

ボリュームはデータの永続化のための仕組みなのでコンテナが破棄されても残ります。
再度 Compose でコンテナを立ち上げると、今度はvoltestには既に先程入れたファイルが存在しており、vol01の内容もvol02の内容も上書きしてしまうためです。

ということで、繰り返しになりますが、

  • マウントするボリュームに何かしらファイルやディレクトリが存在すれば、マウントされるコンテナ側のディレクトリの中身は全部上書きされる。
  • マウントするボリュームに何も入っていなくて、マウントされるコンテナ側のディレクトリに何か入っていれば、ボリュームにコピーされる。

ということが確認できました。

参考文献

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

オリジナルのアプリを完成させるまでの解説

環境

macOS 10.15.5
Rails 5.2.4.2
Docker 19.03.12

概要

オリジナルアプリの概要はCRUDのシステムを意識した簡易的なメモアプリの開発です。
簡易的なアプリと言っても実用性には欠かないよう注意を払いました。行数が増えてもレイアウト崩れが起きないように実装し、文字数制限や空白の項目が新規作成されないようにも設定しました。

Dockerを用いてフレームワークはRailsを使用しました。そしてHerokuにより公開をしています。

オリジナル性について

HTMLに関してはclass名などは学習サイトをヒントに用いて、デザインは外観は学習サイトをヒントにしましたが実装は全て自走で行いました。
Railsの機能の実装に関して事前に学習サイトを何度も繰り返し行い、CRUDの機能を頭に入れてから今回の作成を行いました。そのため短いコードなどはなるべくサイトなどを参考にせず、自分で覚えた内容で実装し、コマンド操作は基本的に全て頭に入れた内容のみで行いました。

サイトについて

スクリーンショット 2020-08-01 23.23.27.png
一覧ページをトップページとして定めメモの項目が個々の詳細が表示できるようにリンク指定をしています。その際に新規投稿された項目が最上部に移動するように実装しました。

lists_controller.rb
class ListsController < ApplicationController
  def index
    @lists = List.all.order(created_at: :desc)
  end

新規作成ページ

スクリーンショット 2020-08-01 23.23.45.png
新規作成ページでは空白の内容と141文字以上の内容が実行されないように設定しています。

list.rb
class List < ApplicationRecord
  validates :content, {presence: true, length: {maximum: 140}}
end

詳細ページ

スクリーンショット 2020-08-01 23.24.43.png
メモ一覧の個々の項目のリンクから移動すると個々の詳細ページが閲覧できます。そこから「編集」と「削除」を実行することができます。

編集ページ

スクリーンショット 2020-08-01 23.24.55.png
編集ページではページを開いたときに編集前の内容が表示されるように実装しています。

edit.html.erb
<div class="form-bady">
  <textarea name="content"><%= @list.content %></textarea>
  <input type="submit" value="編集">
</div>
lists_controller.rb
def edit
  @list = List.find_by(id: params[:id])
end

オリジナルアプリを作るにあたり意識したこと

わたしは自走できるエンジニアとしてスキルを身に付けたい!という思いからどんなやり方がそんなエンジニアに近づける方法なのか良く自問自答をします。今回このシンプルなメモアプリを作成しようと考えたのはRailsのCRUDの機能やMVCは完璧に落とし込もうと考えたのでこのシンプルさにまとめてみました。
今後はログイン機能やユーザーごとのアクセス権限を設けたページの作成などの機能を有したアプリの作成などにも取り組みたいです!

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

メモリ圧迫テストで利用できるコンテナの作り方

インフラ環境の構築や検証をしているとメモリが圧迫された時の挙動を確認したくなる時があるかと思います。
そんな時に以下のコンテナを使うと指定したメモリを専有してくれて便利です。
(k8s環境を想定していますが、dockerさえ入っていればdocker runで起動することが可能です)

構成

・docker-entrypoint.sh
・Dockerfile
・deployment.yml

内容

・docker-entrypoint.sh

#!/bin/sh

MEMORY_USE_M=`echo $(($MEMORY_USE/1024/1024))`

echo "${MEMORY_USE_M}MB"
/usr/bin/stress -m 1 --vm-bytes $MEMORY_USE --vm-hang 0 -q

・Dockerfile

FROM ubuntu:18.04

ENV MEMORY_USE 1134217728

ADD stress_1.0.4-2_arm64.deb .
RUN apt-get install ./stress_1.0.4-2_arm64.deb
ADD docker-entrypoint.sh .

#CMD ["/usr/bin/stress", "-m", "1", "--vm-bytes", "$MEMORY_USE", "--vm-hang", "0", "-q"]
ENTRYPOINT ["sh", "./docker-entrypoint.sh"]

・stress.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: stress
  labels:
    run: stress
spec:
  replicas: 1
  selector:
    matchLabels:
      run: stress
  template:
    metadata:
      labels:
        run: stress
    spec:
      containers:
      - image: stress:latest
        name: stress
        imagePullPolicy: IfNotPresent
        env:
        - name: MEMORY_USE
          value: "2134217728"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCodeでリモートサーバのDockerコンテナに引きこもる for Windows10

背景

TwitterのTLに流れてきたVS Code Meetup #6をなんとなく見ていたんですが、
Shion Tanakaさん(@tnk4on)の発表に触発されました。
Remote-Containersの接続先ホストにFedora CoreOSを使う

やりたいこと

  • ローカルのWindowsマシンからリモートサーバにあるDockerコンテナへアクセスしたい
  • Docker for Windows + VSCodeのようにVSCodeで直接コンテナにアタッチしたい(引きこもりたい)

検証環境

  • リモートサーバ
    • Ubuntu 20.04 LTS(ESXi上のVM)
    • Docker version 19.03.12, build 48a66213fe
    • dockeradminというdockerコマンドを実行できるユーザを作成済み
  • ローカルマシン
    • Windows10 Pro 2004
    • VSCode 1.47.3(Extentionは以下をインストール)
    • Docker for Windows 19.3.08
      (ローカルマシンでDockerコンテナを動かす必要はないのですが、CLIコマンドを実行するために必要。Homeの場合は後述の手順を確認ください)

リモートサーバへのDockerのインストール

Docker公式の手順にてdocker-ceをインストールしてます(Ubuntuのdocker.ioじゃないです)
特記事項はないので省略
あと、多分ですけどリモートサーバのDockerとローカルマシンのDocker CLIはバージョンがあってるほうがよさげ

SSH鍵の用意

今回VSCodeからリモートサーバ側のDockerへのアクセスにはSSHを利用します。
パスワード認証だと、VSCodeのDocker拡張がうまく動いてくれないので、鍵認証する必要があります。

1. キーペアの作成

クライアントで作るべきなんですがめんどくさいのでリモート側で作成しました・・・

# 鍵の作成
dockeradmin@container-engine:~$ ssh-keygen -t rsa -b 4096
# 鍵のコピー
dockeradmin@container-engine:~$ ssh-copy-id dockeradmin@localhost

パスフレーズは入力してません(パスフレーズつけるとうまくいかなかった?)

2. 秘密鍵(id_rsa)をクライアントPCの.sshフォルダにコピー

必ずC:\Users\{username}\.ssh 配下に格納すること。
いくらか確認したのですが他のパスだとうまくいかない

3. ssh-agentに鍵を登録する

これやらないと駄目でした
やってないとVSCodeさんから「これやってみ?」って以下のURL教えてくれます
https://code.visualstudio.com/docs/containers/ssh

Windows (OpenSSH): The latest version(s) of Windows 10 include OpenSSH by default. There is a Windows service, ssh-agent that is disabled by default, and needs to be re-enabled and set to automatic start. From an admin command prompt, run sc config ssh-agent start=auto and net start ssh-agent. Then, do ssh-add <keyfile>.

というわけでやります。

Microsoft Windows [Version 10.0.19041.388]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>sc config ssh-agent start=auto
[SC] ChangeServiceConfig SUCCESS

C:\WINDOWS\system32>net start ssh-agent
OpenSSH Authentication Agent サービスを開始します.
OpenSSH Authentication Agent サービスは正常に開始されました。

C:\WINDOWS\system32>ssh-add c:\Users\rohisama\.ssh\id_rsa
Identity added: c:\Users\rohisama\.ssh\id_rsa (dockeradmin@container-engine)

VSCodeの設定

VSCodeのSettings.jsonを更新

以下を追加するだけです。追加したらVSCodeを再起動しましょう。
IPの部分はご自身の環境にあわせてどうぞ

"docker.host": "ssh://dockeradmin@192.168.0.66",

本番

確認の為、なんでもいいのでリモートサーバ側でDockerのコンテナを動かしておきます。
今回はなんかの練習用に作った mysql-trainingというイメージのコンテナを動かしてます(元イメージはmysql:8)

1. VSCode起動

コンテナを起動したらローカルマシンのVSCodeを起動します。
起動したらDockerのクジラアイコンをクリック
成功している場合、VSCode上でリモートサーバ上で動いているコンテナの状態が確認できると思います(画像左上)
image.png

2. コンテナにアタッチ

いよいよVSCodeからリモートサーバで動いているコンテナにアタッチします・・・
起動しているコンテナを右クリック→Attach Visual Studio Codeと選択(画像参照)
image.png

成功すると新しいウインドウが開くはず
こんな感じ。開いたウィンドウの左下にアタッチ中のコンテナの情報が出ているのが分かります。
image.png

VSCodeからアタッチできるととても便利で、VSCodeからターミナルを開いてコマンド実行なんてお手の物
image.png

コンテナの中にあるファイルをVSCodeで編集するなんてことも可能なんです!!
image.png

一旦終わり(Windows10 Homeの人は続きも見てください)

需要があるかはわかりませんが、応用でクラウド上のコンテナに入るなんてことも可能なんじゃないだろうか。

なお筆者は職業上Javaやったりしてるんですが、VSCodeでDockerコンテナに引きこもれる事が分かってからはローカルマシンにはJDKはインストールせずOpenJdkのコンテナに開発用のソースコード一式置いてからのVSCodeで引きこもって開発してます(Java系のExtentionをインストールすれば割と普通に開発できます)

Windows10 Homeでもリモートサーバのコンテナに引きこもりたいあなたへ

本記事は内部的にDocker CLI(dockerコマンド)を使用している関係で、WindowsにDocker for Windowsをインストールする必要があります。
そのため現状Docker for Windowsがインストール不可であるWindows10 Homeの場合、dockerコマンドが実行できません。
※Insider Preview版だとWSL2使えるのでワンチャンインストール可能なのかもですが未調査です

手元にWindows10 HomeなタブレットPCがあったので確認していたのですが、結果としてはDocker CLIの導入自体は可能でアタッチも問題なく可能なのですが若干の問題があります。
以下の方法を試しました。

古いDocker-CEのバイナリから入手(当環境では無理だった)

google様のお知恵を拝借していると以下の記事がヒット
以下から古いバージョンのDocker-CEのバイナリが入手できます
https://download.docker.com/win/static/stable/x86_64/

docker-17.09.0-ce.zipをDLし解凍するとdocker.exeがあるので、解凍したパスを環境変数のPathに登録することでdockerコマンドが利用可能になります。
ただし、バージョンが古いためかVSCodeからのアタッチは不可でした
(おそらくDocker CLIがSSHアクセスに対応していない?)

Docker for WindowsがインストールされているPCからdocker.exeを持ってくる

デフォルトではC:\Program Files\Docker\Docker\resources\binにdocker.exeがあるので、Windows10 Homeのマシンの任意のパスにコピーします。
環境変数のPathに登録することでdockerコマンドが利用可能となりVSCodeからのアタッチも可能でした。
ただし、この方法にはWindows10 Proが必要になるためあまり現実的ではないかもしれません。
(個別に提供依頼があれば提供できますが・・・していいのか?)

終わり

自身の個人用マシンはWindows10 Proなので、こんな事しなくてもVSCodeでコンテナ内部にアタッチできたりとかなり便利に使えてはいましたが、常にDocker起動していたいわけでもなく、いっそサーバ(ESXi)のVMの一つをコンテナ専用にしてそっちで開発も運用もできたらいいなぁと思い色々調べながら今回ようやく出来たのですが、ゴールに至るまでにズバリな回答を得られなかったので今回の記事作成と相成りました。
どれほどの需要があるかわかりませんが、皆様のコンテナ引きこもり生活の一助となれば幸いです。

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

【Rust】VSCodeを使ったDockerコンテナ上のRustアプリケーションをデバッグする方法

はじめに

最近Rustを触り始めて、コンパイラに怒られる日々を送っているTomoProgです。
この記事ではVSCodeを使い、Dockerコンテナ上で構築したRustアプリケーションをデバッグする方法を説明します。

この記事の対象者

  • Docker上のRustアプリケーションのデバッグ方法を知りたい方

前提

Rustアプリケーションが起動するDockerコンテナが起動していることを前提に話を進めます。
こちらの記事を参考にする場合はDockerコンテナを起動した状態で試してみてください。

筆者の環境

筆者がデバッグ環境を構築した際の環境を載せておきます。
この環境通りでなくても、VSCodeとDockerがインストールされていれば構築できると思いますので、試してみてください。

  • OS
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
  • VSCode
$ code -v
1.47.2
  • Docker
docker -v
Docker version 19.03.12, build 48a66213fe

VSCodeからDockerコンテナに接続する

まずはVSCodeからDockerコンテナに接続できるようにします。
Dockerコンテナへの接続にはRemote-Containersという拡張機能を使います。
Remote-ContainersVSCode Remote Developmentの機能の1つで、この拡張機能を使うことで、Dockerコンテナ内のファイルを直接操作できたり、VSCodeの拡張機能をコンテナ内にインストールできるようになります。
image.png
インストールが終わると画像のように画面の左下に緑色のアイコンが追加されます。
image.png
このアイコンを押すと、Remote-Containersのメニューが表示されるので、Attach to Running Container...を選択します。
image.png
選択すると起動しているDockerコンテナが表示されますので、Rustアプリケーションが起動しているDockerコンテナを選択しましょう。
image.png
VSCodeが新しく立ち上がり、左下の緑色のアイコンが選択したコンテナになっていれば接続成功です。
image.png
もし、以下のようなメッセージが出た場合はdockerコマンドをsudoなしで使用できるようにする必要があります。こちらを参照し設定してみてください。
image.png

Docker上のRustアプリケーションがあるフォルダを開く

次はRustアプリケーションがあるフォルダを開きます。
VSCodeのエクスプローラからフォルダーを開くを選択し、Dockerコンテナ内のRustアプリケーションのフォルダを指定します。
筆者の環境では/work/hello/がRustアプリケーションのフォルダなのでここを指定しています。
image.png
画像のように指定したフォルダの中身がVSCodeのエクスプローラに表示されれば完了です。
image.png

デバッガをインストールする

次はデバッガをインストールしていきます。
デバッガにはCodeLLDBという拡張機能を使います。
CodeLLDBLLDBというデバッガをVSCodeで利用できるようにする拡張機能です。
image.png

インストール完了後、インストールされている拡張機能を確認し、画像のようにLOCALではなくCONTAINERの方にCodeLLDBがインストールされていればデバッガのインストールは完了です。
image.png

launch.jsonを作成する

LLDBを使用したデバッグができるようにlaunch.jsonを作成します。
実行タブを開き、launch.jsonファイルを作成しますを選択し、LLDBを選択します。
image.png
Cargo.tomlが存在すると以下のようなメッセージが表示されるため、「はい」を選択します。
image.png
「いいえ」を選択してもlaunch.jsonは作成されますが、「はい」にすると環境に適したlaunch.jsonを自動で作成してくれるため、非常に便利です。
この記事では「はい」を押して自動生成されたlaunch.jsonを使用しています。

画像のようにエディタにlaunch.jsonが表示されれば作成完了です。
image.png

ここまで設定すればデバッグ環境の構築は完了です。

デバッグする

それでは早速デバッグしてみましょう。
プログラムを一時停止したいところにブレークポイントを設定し、画像左上の再生ボタンを押せばデバッグが始まります。
ブレークポイントはエディタの行番号の少し左をクリックすると、画像のように赤い丸が表示されます。
image.png
画像のように設定したブレークポイントの位置でプログラムが止まれば成功です!
image.png
あとはウォッチ式に変数を追加したり、ステップ実行してみたり色々試してみてください。

まとめ

VSCodeを使ってDockerコンテナ上のRustアプリケーションのデバッグ方法をまとめました。
Dockerコンテナ上のデバッグは何かと面倒なイメージでしたが、VSCode Remote Developmentが登場したことにより、かなり簡単に設定できるようになり感動しました。

それでは良いRustライフを!

TomoProg

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