20190915のdockerに関する記事は12件です。

dockerプライベートリポジトリの作り方

dokcer imageをプライベートリポジトリで利用する方法

目的

ローカル環境にプライベートコンテナリポジトリを作成する

なぜ?

dockerやkubernetesで使用するコンテナイメージを自分用にビルドしたものを保管、管理したい。

どのように?

コンテナイメージを管理する方法はいくつかありますので、以下の中から選択する必要があります。
1.Docker Hubの利用する(有料)
2.amazon ECRを利用する(有料)
3.ローカルオンプレ環境にOSSのリポジトリ環境を構築する

このページでは3の「ローカルオンプレ環境にOSSのリポジトリ環境を構築する」を説明します。

材料

  • サーバ環境:CentOS Linux release 7.6.1810 (Core)
  • ソフト:docker-distribution
  • 作業時間 少々
  • やる気:多め

レシピ1:レジストリサーバのインストール

ソフトウェアをインストール&サービスを起動する

# yum install docker-distribution
# systemctl start docker-distribution.service
# systemctl enable docker-distribution.service

レシピ2:設定情報の変更

レジストリデータ保存先&待ち受けポートの変更

  • 変更必要なら修正する
# vi /etc/docker-distribution/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
    cache:
        layerinfo: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
http:
    addr: :5000

hostsファイルの変更

以下の設定はbuild imageを取得したいノードにて作業が必要です。
- IPv6は無効にします
- ホスト名を登録します

# vi /etc/hosts
#::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
<レジストリサーバーのIPアドレス> kbmster

接続情報を追加

# vi /etc/docker/daemon.json
  "insecure-registries": [
     "kbmaster:5000"
   ]

レシピ3:dockerの再起動

# systemctl daemon-reload
# systemctl restart docker

レシピ4:buildイメージをリポジトリサーバにpushする

# docker build -t wp-tomcat:1.0 .
# docker tag wp-tomcat:1.0 kbmaster:5000/wp-tomcat:1.0
# docker push kbmaster:5000/wp-tomcat:1.0

レシピ5:buildイメージをリポジトリサーバからpullする

各ノードから以下を実行するとdocker imagesがダウンロードされます

# docker pull kbmaster:5000/wp-tomcat:1.0

※参考資料
https://sato-labo.mydns.jp/2018/07/install-docker-registry/
https://tracpath.com/works/devops/docker_hub_and_amazon_ec2_container_registry/#Docker_Hub

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

Docker導入後に使いそうな基本コマンド

Docker概念理解する際に読んだ以下の記事より、使いそうなコマンドをシンプルにまとめてみました。

【図解】Dockerの全体像を理解する -前編-

イメージからコンテナ起動する基本コマンド

$ docker pull centos # Docker Hubからイメージ取得
$ docker create -name [作成コンテナ名] [イメージ名] # イメージからコンテナ作成
$ docker start [コンテナ名] # コンテナを起動
$ docker run hello-world # pull,create,startを同時実行

イメージ

$ docker imaes # 一覧表示
$ docker rmi [イメージID] # 削除

コンテナ

# 一覧表示(-a付きの場合、停止中も含む)
$ docker ps -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
845e015b8f95        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago                       agitated_heisenberg

# 起動、停止、削除、コンテナログイン
$ docker restart # 再起動
$ docker stop # 停止
$ docker rm [コンテナID/名前] # コンテナ削除。不使用コンテナはHDを圧迫するので削除する
$ docker exec -it [起動中コンテナ名] # 起動中コンテナにシェル接続、exitしてもコンテナは停止なし

# コンテナからイメージ作成
$ docker commit [コンテナ名] [image名:tag名] # 現状コンテナの状態をイメージに保存する
$ docker build -t [ビルドイメージ名] . # 独自イメージをビルド
$ docker build -no-cache -t [ビルドイメージ名] # 独自イメージをキャッシュなしでビルド
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FOSS4G 2019 Niigata で得たものの整理

ハンズオンマテリアル関係

こちらこちらを用いて、柴本さん・松澤さんとともにハンズオンを行なった。

asciinema を使うようにしたい

ango の開発の際に検討はしていて採用はしていなかったのだが、やはりasciinema のような CUI のスクリーンキャストを使う等にすると良いと思う。

なぜなら、聴講者に対して「何がコマンド入力で、何がコマンド出力か」を確実に伝えるのは、スタティックな表示では難しいからだ。

modify.js や modify.sql の意義を丁寧に説明する

国連ベクトルタイルツールキットはストリーム志向のソフトウェアなのだが、その処理の中で modify.js や modify.sql が入る理由について、今回は質問をいただいた。

次のような理由を、積極的に説明していくことが適切だと思う。

  1. modify.js を使うことで、中間ファイルの保存を行わずに済ませ、ストレージを節約するとともに、処理速度を向上することができる。
  2. ベクトルタイルの生産担当者には、必ずしもマスターデータを変更する権限がない場合が多い。ベクトルタイル生産の都合によるデータの調整は、マスターデータに対しては行えないので、modify.js を使う。

そもそもベクトルタイルとは何かについて説明する

私は次のように説明します。

  1. ウェブ地図では地図を細切れに分けてストリームするが、その細切れのことをタイルと言い、タイルには画像タイルやベクトルタイルがある。画像タイルもベクトルタイルも表示された見た目は同じ。
  2. しかし、画像タイルはレンダリングした画像であり、ベクトルタイルは機械可読なデータである。
  3. 画像よりもデータの方が75%ほど軽い。その軽さがイノベーションをもたらす。

スマートな Raspberry Pi の使い方

PC に Raspberry Pi をイーサネットケーブルで直結して、 raspberrypi.local というホスト名に ssh するという方法がもっともスマートであるように思われる。

電源ケーブルとイーサネットケーブルを十分短いものにすれば、かなりスマートな提示ができると思われる。

実際には、PC 側に必ずしもイーサーネットポートがあるわけではないので、USB/イーサネット変換や、USB-C/イーサネット変換のアダプタもある程度の数持っておく必要があると考える。

Docker Toolbox ではポート転送が必要

Docker Toolbox を使う人に対しては、 Oracle VirtualBox でポート転送を設定してもらう必要がある。そのほかの場合には、既存の案内内容で十分にポート転送ができている。

自ホスト名をスマートに扱う

自ホスト名が localhost になるパターンと raspberrypi.local になるパターンが発生し、 style.(h)json を書き換える必要が発生した。

自ホスト名を config/default.hjson あたりに逃し、rake build の時に自ホスト名を style.json に埋め込むようにすると、面倒な編集が不要になる。

自ホスト名は、タイルのテンプレート URL、スプライトの URL、フォントの URL と三回使われることになるので、rake build のときに埋めるようにしたほうが安全、ということである。

tippecanoe のコマンドラインオプションは short form? long form?

ango では、私が long form のオプションを使い、柴本さんが short form のオプションを使った。統一できた方が良い。

私は rake にコマンドを書いて、研修の中で解説だけすることにしたので、long form を使った一方、柴本さんはコマンドを直接打ってもらうことにしたので、short form を使ったのである。よって、rake を使うかどうかの判断に合わせて、long か short かを決断すれば良いと思う。

地球地図に取り組んでいく

地球地図はすでにベクトルタイルにされているから、ハンズオンにそれをなぞるような感じになる。まずは、地球地図 GeoJSONS を optgeo の中に作るのも一つの方法だと思う。

レポジトリを私が作るとしたら Inazo という名前にすると思う。

サポート要員の数

サポート要員の必要数は、同時に発生するサポート要求の数に合わせれば良い。今回はサポート要員2名で16名程度への対応であったので、かなり余裕を持って対応することができた。最小のサポート要員数は1だと思う。サポート要員をゼロにして講師だけで対応しようとすると、ハンズオンの質がかなり下がる可能性がある。

プレゼンテーションの内容関係

こちらのプレゼンテーションを行なった。

適切なガバナンスの確保について

OSGeo Incubation Process への応募を長期的に目指していくことで、オープンソースプロジェクトとしての適切なガバナンスを得ていくことを目指す。

そのための課題は、ここでじわじわと検討していくことになる。

統制されたネットワークへの対応について

次の世代のハンズオンマテリアルについて作業をするにあたって、「インターネットから独立したウェブ地図」として動作するようになることをまず目指す。

FOSS4G Monthly Online について

Zoom を使って月例開催する方向で考えていくが、目標は10月の第三木曜日に初実施、というあたりだと考えている。

ツールの勉強

とりあえず、次の二つのツールについて、動き始める前に勉強をしておく必要があると認識している。

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

未経験で新規案件でインターンして学んだこと(学生です)

どんな目的で記事を書いているか

とにかくアドバイスが欲しいです(切実)
・技術がどう身についていったかの過程を示してエンジニアで人事をやっている方にいい情報が届くといいな
・今エンジニア目指してる人の就活のお助けにもなったらいいな

自分のステータス

・理系大学院生
・開発経験なし、研究のためにプログラミングは少しやっていた
・触れたことある言語はjava,Ruby,ほんの少しC
・今開発で使っているのはphp(laravel),JavaScript(VueとJQuery)
・インターン初めて今ちょうど4ヶ月くらい

何をどう学んだか

インターンで初めて本格的な環境開発した
インターンするまではDocker使ったことなかったです。もうなにも知らなかった。もちろんPHPも触ったことなし。
でも会社入ったら一番最初に環境開発して〜と言われて何もわからずめっちゃDocker勉強しました。開発の環境は先輩に教えてもらいながらなんとかできたけど、理解できていなかったからDockerの参考書使って自分で0から開発環境作ってみました。これでかなり理解深まった。
そして記念すべきQiita初投稿がこれ
Dockerでnginx+MySQL+Laravelの環境構築からプロジェクト作成・DBへのマイグレーションまで

フレームワークってすごい
今までデータベースを扱ったことがなく、sql文とかも勉強しながら開発してたのですが、フレームワークというものがあったおかげでものすごく理解が早くなった。言語の中身・特徴理解する前にフレームワーク使うのはよくないと言われていますが、自分の場合はフレームワークから入って成長できたと思っています。

とにかく実装できないことが恥ずかしいと思って必死に勉強した
これは環境にもよると思いますが、全く未経験なのにガンガンタスク振られて焦りました。できないです、とか間に合わなかったですを言いたくなくて死に物狂いで勉強しました。

人のコード見て学べる、自分のコードのレビューがもらえる
サービス作ってない時は計算できていればいいやと思っていたものが、現場になると可読性や処理速度を気にするようになった。ただ動けば良いだけではないことを実感できた。

コミュニケーションすごく大切
一人でやっていれば仕様に迷いはないですが、チームの開発だと要件にマッチした実装になっているかがすごく大事。「多分こうだろう」と思って実装したことが無駄になったことがあり、仕様の認識違いがないか都度確認することがとても重要だと学びました。

使えるものは使いまくる
案件によるかもしれませんが、便利なライブラリはどんどん使うべきだと思います。最初は知らないものを使うことに抵抗がありましたが今では新しいものどんどん使いたくてたまらない!とうう感じになってます。その例がこの記事。
Lalavel ScoutでAlgoliaを使って全文検索を実装してみた!
ClosureTableを使って〇〇年のアニメを季節ごとに1テーブルで管理する

公式ドキュメントは神!特に英語版!!!!!!
自分はとても英語が苦手だったのですが、物によっては英語のドキュメントしかない場合があります(Algoliaも英語しかない)。どうしても英語を読まなければいけない状況になってから、「英語の方がわかりやすい!」となりました。日本語にこだわらずになんでも英語で調べたり読んだりすると知識増えるなと思います。

新しい情報に敏感になることが大事
ITの世界は多分他の業界より発展速度が速い。いつまでも昔のやり方にとらわれずにどんどん新しいもの使ってあわよくば自分が新しいツール開発するくらいの意気込みを持っていた方が良い。実年齢は年取っても技術の話では若くいたい!

0から作ることは自信になる
まだリリースはしていないのですが、新規だからこそ今自分が作ったものがリリースされるのが楽しみで仕方ないです。ワクワクが止まらん!

書籍は自分で持っていた方がいい
わからないことは調べれば出てくるという人もいますが、自分は本を買うことを勧めます。わからないことを調べているうちに別のことも学べるので絶対投資すべき!

最後に

とにかくいろんな技術者の人と話していろんなことを吸収していきたいです。YYPHPいきたかったのに終わってしまたの悲しい。。。。。何かいいコミュニティあったら教えてください。

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

[備忘] Container RegistryにDocker Imageをpushする

完全に備忘

はじめに

プライベートにDocker Imageを管理したい場合は、Container Registryを使うことにした
費用はCloud Storageと下りの費用くらいなのでほぼ無視できる。はず。。。

Container Registryの公式ページ

1. Dockerhubから自分が欲しいDocker Imageを取ってくる

dockerhubから自分が欲しいDocker Imageをpullしてくる

今回はnodejsの公式イメージをpullしてくる

docker pull node

特にタグを指定してないのでlatestがpullされる

2. gcloudでcloud container registryへの認証を通す

GoogleCloudPlatformの場合には、cloudshellで実施するのが楽で良い

Container RegistryのAPIを有効にしておくのを忘れずに

で、認証のコマンドはこれ

gcloud auth configure-docker

3. Imageにタグをつける

ローカルにpullしてきたイメージを特定の場所にpushするにはタグ付けが必要なので、タグ付けする

docker tag node:latest gcr.io/{Project_name}/node:tag-first

一応タグ付けされたかを確認しておく

docker images
output
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
node                              latest              d8c33ae35f44        3 days ago          907MB
gcr.io/{Project_name}/node       tag-first           d8c33ae35f44        3 days ago          907MB

4. Imageをpushする

最後にタグ付けされたImageをContainer Registryをpushする

docker push gcr.io/{Project_name}/node:tag-first

コンソールでContainer Registryに登録されているか確認する

確かに登録されていることを確認

5. いらないImageは削除する

少額とはいえ課金対象ではあるので、使わないImageは消しておきたい

gcloud container images delete gcr.io/{Project_name}/node:tag-first --force-delete-tags

参考リンク

Googleの提供するDocker Registry の Google Container Registryを試す
Google Container Registry概要
Container Registry クイックスタート

おしまい

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

Wiki.jsっていうWikiのOSSを使ってみる

以前とある件でwikiを作ってみようかなとツイートしたところ、
フォロワーさんより

Wiki.jsいいぞ

って教えてもらったので、まずはちょっと試してみよう。
Beta版があるらしいので、そちらを使います。
ドキュメントがしっかりしているので、
英語とか全然問題ない方はこちらを参考にした方が早いかも。

前提条件

Macを使用
Dockerがインストールされている

環境構築

Dockerに既にイメージを作ってあるみたいなので、
このページの下にあるdocker-composeをコピペしてあげるだけです。
両方ともイメージがあるのでそのまま起動します。

$ docker-compose up
そうするとコンソールにこのように表示されました。
http://localhost:3000/ にアクセスすればいいみたいですね。

アクセスしたら管理者のログイン情報を入力する画面が表示されます。

Allow Telemetryの項目は、開発者に開発のための情報を提供しますか?てきなものです。 INSTALLをクリックするとログイン画面に遷移し、ログインするとこのような画面になりました。
めっちゃUIが好みすぎる。
CREATE HOME PAGEをクリック。
エディターを好みなものに選択できるようですね。

ただいろいろ表示されていますが、現状はMarkdown EditorVisual Editorしか使えないみたい。
Markdownがあれば十分なのでMarkDownをクリック。 ページの詳細を設定できます。
タブにあるSCHEDULINGSOCIALはまだ使えないみたい。
おおおかっけええ!
リアルタイムでプレビューがみれる。
画像などはサイドメニューから入れられるみたい。
フォルダー形式で管理できるのか。すぎょい。
編集できたらCREATEをクリック。
このような感じになります。
管理画面から差分も見れるみたい。

感想

Wikiの基幹的なシステムは既にあるから使えるには使えそうですね。
UIも好みすぎるし、wikiつくるってことになったら是非使ってみたい。
これからもっと多機能化していくみたいですし、今後に期待。

リンク集

公式サイト
GitHub
デモ兼ドキュメント

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

cacheのヒット率を測定するツールを作成しました

Cacheのヒット率測定ツール

Webアプリケーションのインフラを考えるうえで、静的コンテンツ等をCDN配信にする選択肢を取ることが多いかと思います。
(例えば、さくらCDNやAWSならCloudFrontなど)

運用していくうえで、画面ごと(URLごと)にキャッシュのヒット率キャッシュされていないコンテンツを洗い出すツールを作成しました。

https://github.com/hirotoyoshidome/hit_rate

Docker化していますが、seleniumを利用していてchromediriverのバージョンによっては
上手く動かない場合があるようです。

その場合は、申し訳ないですが、各自のローカル環境で動かしてみてください。
※そのうち直すかもです

* selenium
* requests
↑のみ利用しています

もっと良いやり方があれば、ご教示ください!
では、今回はこのへんで!

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

WSLでdocker-ceを動作させる手順

設定済みWSL上にDockerをインストールして、hello-worldするところまで行います。

docker-compose(複数コンテナの連携)は、WSL上で、iptablesが完全にサポートされていないとのことなので、動作しません。

Dockerは、17.09.1以上だと動作しないため、17.09.0-ceをインストールして動作させています。

WSLを使用可能にする設定と、Ubuntuの導入はこちらに書きました。

動作環境

  • Microsoft Windows 10 Enterprise Evaluation ver:1809 build:17763.737
  • Ubuntu 18.04.3
  • Docker 17.09.0-ce

Ubuntuバージョン確認

ubuntuはWindows管理者権限で実行します。

$ head -n 2 /etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"

Dockerインストール

# 古いバージョンのdockerは、トラブルの原因になるので、アンインストール
$ sudo apt-get remove docker docker-engine docker.io containerd runc
$ sudo apt-get autoremove
$ sudo rm -rf /var/lib/docker # イメージファイル等の格納先、uninstallでは消えないので直接削除

# Docker 17.09.1からWSL未サポートな機能があるため、Docker17.09.0をダウンロード&インストール
$ curl -O https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_17.09.0~ce-0~debian_amd64.deb
$ sudo apt install libltdl7 -y # 依存pkgもインストール、ないとエラーになります。
$ sudo dpkg -i docker-ce_17.09.0\~ce-0\~debian_amd64.deb

Docker動作確認

# バージョン確認
$ docker -v
Docker version 17.09.0-ce, build afdb6d4

# Doker起動
$ sudo service docker start
$ sudo service docker status
[sudo] password for user:
 * Docker is running

# コンテナ起動
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
・
・

docker.ioのdockerでは動作しなかったり、古いバージョンのUbuntuで試してみたりと、いろいろ回り道しましたが、無事に起動できました。これからいろいろ遊んでみます。

## 参考URL
WSL上でDockerが動くという噂
どうしても Docker on Ubuntu 18.04 on WSL したかった

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

dockerの置き換えを目指す ルートレス&デーモンレスの podman 入門

OpenShiftのマニュアルには、dockerコマンドと共に podmanコマンド が利用できるとされている。OpenShift を触る様になるまで、podmanの存在を知らなかったので、調べたことをメモとして残しておく。

podman とは?

このpodmanという名前は、コンテナだけでなく、Kubernetesのポッドの形態でコンテナを起動できることを期待させてくれる。プロジェクトのウェブページから特徴を拾うと次の7つがある。そして、プロジェクトのページの前面には出ていないが、Podmanには、ポッドのマニフェストを生成したり、コンテナを起動する機能もある。Podmanロゴは、可愛いもの路線で、複数のコンテナが内部で動くポッドを実行できることを感じさてくれる。

Podman の特徴

(1) Docker互換のコマンドラインフロントエンドを提供

最も簡単にいうと、alias docker = podman ということだ。つまり、docker コマンドの代わりに、podmanで代用できることを意味する。

(2) オープンソースプロジェクトであり、GitHub でコードが公開されている

このプロジェクトは Red Hat によって運営されており、Fedora、Red Hat Enterprise Linuxの最新リリースバージョン、および Ubuntuに対して、ビルドをテストしている。

podmanのバンドル状況について、調べたところ、2019年9月現在で、次の表の状況がわかった。問題なく動作するのは Fedora 30 だけで、RHEL8はバージョンが古くルートレスモードが実装されていないなどの問題があった。RHEL7/CentOS7 でも動作するとされているが、ルートレスで動作させることができなかった。

Distribution Status Podman version Remarks
Fedora 30 GA 1.5.1 sudo なしの rootlessモードで実行可能
RHEL 8.0 GA 1.0.5 rootlessモード未実装
RHEL 7.6 GA 1.4.4 sudo podman で実行
CentOS 7.6 GA 1.4.4 同上
Ubuntu 18.04 GA 1.5.1 sudo なしの rootlessモードで実行可能

このことから、podman は Red Hat がオープンソース・プロジェクトとして、発展途上であると見なされ、dockerコマンドを置き換えるまでに熟成されるには、もう少し時間が必要と考えられる。

(3) OCIに準拠するコンテナイメージの開発、管理、および、コンテナとして実行

Docker Hubに登録されたコンテナを実行すること、podmanでビルドして、レジストリに登録したイメージを、dockerコマンドで実行することも可能であり、互換性に問題はないと見られる。

(4) デーモンレスのコンテナエンジン

podman は、Dockerデーモンの様な root で動作するデーモンを必要としない。つまり、podman コマンドだけで、デーモンの助けを必要とせずにコンテナを実行できる。

(5) コンテナはルートレスモードで実行可能

ルートレスのコンテナは、それらを起動したユーザーよりも多くの特権を持つことはない。もちろん、root権限で実行されるDockerデーモンでも、コンテナが起動したユーザー以上の権限を持つことが無い様に考慮されているが、もしも、悪意のあるプログラムに隔離が突破された場合のリスクは大きい。その点で、ルートレスは明白なため安心感がある。

次は、podman で実行した場合のコンテナホスト上のプロセスのリストで、この中でコンテナのプロセスは、PID 21710 とその子プロセスである。 これらのプロセスの USER は、rootではなく、vagrant という一般ユーザーになっている。

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vagrant  21729  0.0  0.1   4336  2760 pts/0    S    13:21   0:00 /usr/bin/slirp4netns --api-socket /run/user/1000/libpod/tmp/35de2a668cad2
vagrant  21710  0.0  0.0  80348  2012 ?        Ssl  13:21   0:00 /usr/libexec/podman/conmon --api-version 1 -c 35de2a668cad28fa366c233a641
vagrant  21721  0.0  0.1  11688  2624 ?        Ss   13:21   0:00  \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; done
vagrant  21740  0.0  0.1  43988  3364 ?        S    13:21   0:00      \_ /usr/bin/nc -l -p 3306
vagrant  21707  0.0  0.1   5756  3208 ?        Ss   13:21   0:00 /usr/bin/fuse-overlayfs -o lowerdir=/home/vagrant/.local/share/containers
vagrant  21478  0.0  1.8  80508 37540 ?        S    13:19   0:00 podman

対比のために、Docker で同じコンテナを実行した場合のコンテナホスト上のプロセスのリストである。コンテナは PID番号 5339 のプロセスとその子プロセスですが、USER は全て root になっている。

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      5339  0.0  1.8 880444 37108 ?        Ssl  13:46   0:00 /usr/bin/containerd
root      7684  0.0  0.2  10744  4724 ?        Sl   13:49   0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.conta
root      7707  0.2  0.1  11692  2560 ?        Ss   13:49   0:00      \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; d
root      7757  0.0  0.1  43992  3452 ?        S    13:49   0:00          \_ /usr/bin/nc -l -p 3306
root      5701  4.4  4.4 1114504 90648 ?       Ssl  13:46   0:10 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root      7678  0.0  0.1 305136  2964 ?        Sl   13:49   0:00  \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -co

Docker 19.03 から rootless のコンテナが実行できる様になったが、podman では、よりシンプルに、デーモンレス + ルートレス である。

(6) ほとんどのLinuxプラットフォームで利用できる

パッケージマネージャーでインストールするだけで、簡単に動くかは解らないが、Arch Linux & Manjaro Linux, Fedora, CentOS, Gentoo, MacOS, openSUSE のインストール手順が https://podman.io/getting-started/installation に公開されている。

(7) Kubernetes の Pod を扱える

前面に出されていないが、GitHub の Docs には、マニュアルが整備されていて、その中にはポッドに関するものが多数ある。
ポッド関連のサブコマンドのリストは、https://github.com/containers/libpod/blob/master/docs/podman-pod.1.md でみることができる。

podmanの今後の計画(ロードマップ)

podmanは、バージョン 1.0 に到達しているものの、更なる開発を計画されている。

  • Podman CLIが Varlinkバックエンドを使用して、MacおよびWindowsから、リモートPodmanインスタンスに接続を実装
  • libpodをCRI-Oに統合して、既存のコンテナー管理バックエンドを置き換え
  • podman podコマンドのさらなる機能追加
  • ルートレスコンテナのさらなる改善

https://github.com/containers/libpod

Podman の Pod 関連の機能を試してみる

Podman のドキュメントを見ると、Kubernetes の pod のマニフェスト生成機能、 podマニフェストからpodの起動機能がある。https://github.com/containers/libpod/tree/master/docs

これは、試してみたくなるので、好奇心のままに、少し遊んでみる。
まずは、普通にnginxのコンテナを起動する。このコンテナから Kubernetesのマニフェストを生成してみたい。

[vagrant@fedora30 ~]$ podman run -d -p 8080:80 nginx
Trying to pull docker.io/library/nginx...
Getting image source signatures
Copying blob b8f262c62ec6 done
Copying blob 22a7aa8442bf done
Copying blob a6639d774c21 done
Copying config ab56bba913 done
Writing manifest to image destination
Storing signatures
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                                                                  COMMAND               CREATED        STATUS            PORTS                   NAMES
e65c77446461  docker.io/library/nginx:latest                                         nginx -g daemon o...  5 seconds ago  Up 4 seconds ago  0.0.0.0:8080->80/tcp    elated_taussig

[vagrant@fedora30 ~]$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

podman で コンテナからポッドのマニフェストを生成

実行中のコンテナの名前、または、CONTIAINER ID を指定して、YAML形式のマニフェストを生成できる。

vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS            PORTS                 NAMES
e65c77446461  docker.io/library/nginx:latest  nginx -g daemon o...  6 minutes ago  Up 6 minutes ago  0.0.0.0:8080->80/tcp  elated_taussig

[vagrant@fedora30 ~]$ podman generate kube elated_taussig
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.5.1
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2019-09-14T18:00:49Z"
  labels:
    app: elatedtaussig
  name: elatedtaussig
spec:
  containers:
  - command:
    - nginx
    - -g
    - daemon off;
    env:
    - name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
    - name: container
      value: podman
    - name: NGINX_VERSION
      value: 1.17.3
    - name: NJS_VERSION
      value: 0.3.5
    - name: PKG_RELEASE
      value: 1~buster
    image: docker.io/library/nginx:latest
    name: elatedtaussig
    ports:
    - containerPort: 80
      hostPort: 8080
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    workingDir: /
status: {}

Kubernetesマニフェストから、コンテナを実行

マニフェストを生成して、既存のコンテナを停止させる。

[vagrant@fedora30 ~]$ podman generate kube elated_taussig > pod.yaml

[vagrant@fedora30 ~]$ podman kill elated_taussig
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

生成されたマニフェストを指定して、コンテナを実行する

[vagrant@fedora30 ~]$ podman play kube pod.yaml
a container exists with the same name (elatedtaussig) as the pod in your YAML file; changing pod name to elatedtaussig_pod
Pod:
475a420c00e777182de6e294f83d68e48e646bc3c3b8912ebdcf8aa19f014ec7
Container:
adbb48def6a8ed85db124f54e5b7d249006f6b1bf57fe303b5b8fa444d882fde

以下の様に、コンテナとして起動していることを確認できる。

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS                 NAMES
adbb48def6a8  docker.io/library/nginx:latest  nginx -g daemon o...  25 seconds ago  Up 25 seconds ago  0.0.0.0:8080->80/tcp  elatedtaussig

ポッドとして扱うコマンドも用意されている。

[vagrant@fedora30 ~]$ podman pod ps
POD ID         NAME                STATUS    CREATED          # OF CONTAINERS   INFRA ID
475a420c00e7   elatedtaussig_pod   Running   37 seconds ago   2                 3659edba15a5

podmanは サイドカーを実行できるか?

サイドカーを持つポッドのマニフェストを利用して、podman のロゴが象徴する複数のコンテナを一まとめにして動作させることができるか、確認してみる。
GitHubからサイドカーを持つポッドのマニフェストをクローンして、podman play kube filename で実行してみる。

[vagrant@fedora30 ~]$ git clone https://github.com/takara9/codes_for_lessons
[vagrant@fedora30 ~]$ cd codes_for_lessons/step07/sidecar/
[vagrant@fedora30 sidecar]$ ls
Dockerfile  contents-cloner  webserver.yml

次は、マニフェストのリストである。二つのコンテナ間は、emptyDir というストレージで連携する。

webserver.yml
## サイドカーポッドのサンプル
#
apiVersion: v1
kind: Pod
metadata:
  name: webserver
spec:
  containers:          ## メイン コンテナ
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: contents-vol
      readOnly: true

  - name: cloner       ## サイドカー コンテナ
    image: maho/c-cloner:0.1
    env:
    - name: CONTENTS_SOURCE_URL
      value: "https://github.com/takara9/web-contents"
    volumeMounts:
    - mountPath: /data
      name: contents-vol

  volumes:             ## 共有ボリューム
  - name: contents-vol
    emptyDir: {}

次は、podman play kube webserver.yml で実行した結果である。
残念ながら、サイドカーの中のコンテナを連携させるための 共有ボリュームで エラーが発生した。まだ、これからという感じだ。

[vagrant@fedora30 sidecar]$ podman play kube webserver.yml
Error: HostPath is currently the only supported VolumeSource

おそらく、共有ボリュームを必要としないタイプのサイドカーであれば、問題なく動作するであろう。しかし、その様な例は稀だと思う。

感想

Podman は、dockerコマンドを置き換える目的で、開発されている ルートレス、デーモンレスのコンテナ開発と実行環境である。また、その名前が示す様に、Kubernetesのポッドを実行できることも目指している。Red Hat が立ち上げたオープンソースプロジェクトであり、コミッターのリストをみると、Red Hatの社員が牽引している。そのためか、RHELよりも、Fedoraで最新のバージョンが利用できる。 また、様々な Linux Distribution にも対応すると宣言して、業界でよく知られたメジャーな存在となることを目指していることが伺われる。

個人的には、Dockerはコンテナの世界を幅広く世の中に知らしめ、コンテナの流通の仕組みを作るなど、IT業界への多大な貢献があるにも関わらず、どうして、ここまで置き換え様とされるのか、少々不敏な印象を受ける。 Dockerが非常に価値があることの裏返しでもあると思う。

これからのpodman の動向は注視していきたい。

その他の参考資料

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

Dockerの置き換えを目指す ルートレス&デーモンレスの Podman 入門

OpenShiftのマニュアルには、dockerコマンドと共に podmanコマンド が利用できるとされている。OpenShift を触る様になるまで、Podmanの存在を知らなかったので、調べたことをメモとして残しておく。

Podman とは?

このpodmanという名前は、コンテナだけでなく、Kubernetesのポッドの形態でコンテナを起動できることを期待させてくれる。プロジェクトのウェブページから特徴を拾うと次の7つがある。そして、プロジェクトのページの前面には出ていないが、Podmanには、ポッドのマニフェストを生成したり、コンテナを起動する機能もある。Podmanロゴは、可愛いもの路線で、複数のコンテナが内部で動くポッドを実行できることを感じさてくれる。

Podman の特徴

(1) Docker互換のコマンドラインフロントエンドを提供

最も簡単にいうと、alias docker = podman ということだ。つまり、docker コマンドの代わりに、podmanで代用できることを意味する。

(2) オープンソースプロジェクトであり、GitHub でコードが公開されている

このプロジェクトは Red Hat によって運営されており、Fedora、Red Hat Enterprise Linuxの最新リリースバージョン、および Ubuntuに対して、ビルドをテストしている。

podmanのバンドル状況について、調べたところ、2019年9月現在で、次の表の状況がわかった。問題なく動作するのは Fedora 30 だけで、RHEL8はバージョンが古くルートレスモードが実装されていないなどの問題があった。RHEL7/CentOS7 でも動作するとされているが、ルートレスで動作させることができなかった。

Distribution Status Podman version Remarks
Fedora 30 GA 1.5.1 sudo なしの rootlessモードで実行可能
RHEL 8.0 GA 1.0.5 rootlessモード未実装
RHEL 7.6 GA 1.4.4 sudo podman で実行
CentOS 7.6 GA 1.4.4 同上
Ubuntu 18.04 GA 1.5.1 sudo なしの rootlessモードで実行可能

このことから、podman は Red Hat がオープンソース・プロジェクトとして、発展途上であると見なされ、dockerコマンドを置き換えるまでに熟成されるには、もう少し時間が必要と考えられる。

(3) OCIに準拠するコンテナイメージの開発、管理、および、コンテナとして実行

Docker Hubに登録されたコンテナを実行すること、podmanでビルドして、レジストリに登録したイメージを、dockerコマンドで実行することも可能であり、互換性に問題はないと見られる。

(4) デーモンレスのコンテナエンジン

podman は、Dockerデーモンの様な root で動作するデーモンを必要としない。つまり、podman コマンドだけで、デーモンの助けを必要とせずにコンテナを実行できる。

(5) コンテナはルートレスモードで実行可能

ルートレスのコンテナは、それらを起動したユーザーよりも多くの特権を持つことはない。もちろん、root権限で実行されるDockerデーモンでも、コンテナが起動したユーザー以上の権限を持つことが無い様に考慮されているが、もしも、悪意のあるプログラムに隔離が突破された場合のリスクは大きい。その点で、ルートレスは明白なため安心感がある。

次は、podman で実行した場合のコンテナホスト上のプロセスのリストで、この中でコンテナのプロセスは、PID 21710 とその子プロセスである。 これらのプロセスの USER は、rootではなく、vagrant という一般ユーザーになっている。

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vagrant  21729  0.0  0.1   4336  2760 pts/0    S    13:21   0:00 /usr/bin/slirp4netns --api-socket /run/user/1000/libpod/tmp/35de2a668cad2
vagrant  21710  0.0  0.0  80348  2012 ?        Ssl  13:21   0:00 /usr/libexec/podman/conmon --api-version 1 -c 35de2a668cad28fa366c233a641
vagrant  21721  0.0  0.1  11688  2624 ?        Ss   13:21   0:00  \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; done
vagrant  21740  0.0  0.1  43988  3364 ?        S    13:21   0:00      \_ /usr/bin/nc -l -p 3306
vagrant  21707  0.0  0.1   5756  3208 ?        Ss   13:21   0:00 /usr/bin/fuse-overlayfs -o lowerdir=/home/vagrant/.local/share/containers
vagrant  21478  0.0  1.8  80508 37540 ?        S    13:19   0:00 podman

対比のために、Docker で同じコンテナを実行した場合のコンテナホスト上のプロセスのリストである。コンテナは PID番号 5339 のプロセスとその子プロセスですが、USER は全て root になっている。

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      5339  0.0  1.8 880444 37108 ?        Ssl  13:46   0:00 /usr/bin/containerd
root      7684  0.0  0.2  10744  4724 ?        Sl   13:49   0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.conta
root      7707  0.2  0.1  11692  2560 ?        Ss   13:49   0:00      \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; d
root      7757  0.0  0.1  43992  3452 ?        S    13:49   0:00          \_ /usr/bin/nc -l -p 3306
root      5701  4.4  4.4 1114504 90648 ?       Ssl  13:46   0:10 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root      7678  0.0  0.1 305136  2964 ?        Sl   13:49   0:00  \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -co

Docker 19.03 から rootless のコンテナが実行できる様になったが、podman では、よりシンプルに、デーモンレス + ルートレス である。

(6) ほとんどのLinuxプラットフォームで利用できる

パッケージマネージャーでインストールするだけで、簡単に動くかは解らないが、Arch Linux & Manjaro Linux, Fedora, CentOS, Gentoo, MacOS, openSUSE のインストール手順が https://podman.io/getting-started/installation に公開されている。

(7) Kubernetes の Pod を扱える

前面に出されていないが、GitHub の Docs には、マニュアルが整備されていて、その中にはポッドに関するものが多数ある。
ポッド関連のサブコマンドのリストは、https://github.com/containers/libpod/blob/master/docs/podman-pod.1.md でみることができる。

Podmanの今後の計画(ロードマップ)

podmanは、バージョン 1.0 に到達しているものの、更なる開発を計画されている。

  • Podman CLIが Varlinkバックエンドを使用して、MacおよびWindowsから、リモートPodmanインスタンスに接続を実装
  • libpodをCRI-Oに統合して、既存のコンテナー管理バックエンドを置き換え
  • podman podコマンドのさらなる機能追加
  • ルートレスコンテナのさらなる改善

https://github.com/containers/libpod

Podman の Pod 関連の機能を試してみる

Podman のドキュメントを見ると、Kubernetes の pod のマニフェスト生成機能、 podマニフェストからpodの起動機能がある。https://github.com/containers/libpod/tree/master/docs

これは、試してみたくなるので、好奇心のままに、少し遊んでみる。
まずは、普通にnginxのコンテナを起動する。このコンテナから Kubernetesのマニフェストを生成してみたい。

[vagrant@fedora30 ~]$ podman run -d -p 8080:80 nginx
Trying to pull docker.io/library/nginx...
Getting image source signatures
Copying blob b8f262c62ec6 done
Copying blob 22a7aa8442bf done
Copying blob a6639d774c21 done
Copying config ab56bba913 done
Writing manifest to image destination
Storing signatures
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                                                                  COMMAND               CREATED        STATUS            PORTS                   NAMES
e65c77446461  docker.io/library/nginx:latest                                         nginx -g daemon o...  5 seconds ago  Up 4 seconds ago  0.0.0.0:8080->80/tcp    elated_taussig

[vagrant@fedora30 ~]$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

podmanコマンド で コンテナからポッドのマニフェストを生成

実行中のコンテナの名前、または、CONTIAINER ID を指定して、YAML形式のマニフェストを生成できる。

vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS            PORTS                 NAMES
e65c77446461  docker.io/library/nginx:latest  nginx -g daemon o...  6 minutes ago  Up 6 minutes ago  0.0.0.0:8080->80/tcp  elated_taussig

[vagrant@fedora30 ~]$ podman generate kube elated_taussig
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.5.1
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2019-09-14T18:00:49Z"
  labels:
    app: elatedtaussig
  name: elatedtaussig
spec:
  containers:
  - command:
    - nginx
    - -g
    - daemon off;
    env:
    - name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
    - name: container
      value: podman
    - name: NGINX_VERSION
      value: 1.17.3
    - name: NJS_VERSION
      value: 0.3.5
    - name: PKG_RELEASE
      value: 1~buster
    image: docker.io/library/nginx:latest
    name: elatedtaussig
    ports:
    - containerPort: 80
      hostPort: 8080
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    workingDir: /
status: {}

Kubernetesマニフェストから、コンテナを実行

マニフェストを生成して、既存のコンテナを停止させる。

[vagrant@fedora30 ~]$ podman generate kube elated_taussig > pod.yaml

[vagrant@fedora30 ~]$ podman kill elated_taussig
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

生成されたマニフェストを指定して、コンテナを実行する

[vagrant@fedora30 ~]$ podman play kube pod.yaml
a container exists with the same name (elatedtaussig) as the pod in your YAML file; changing pod name to elatedtaussig_pod
Pod:
475a420c00e777182de6e294f83d68e48e646bc3c3b8912ebdcf8aa19f014ec7
Container:
adbb48def6a8ed85db124f54e5b7d249006f6b1bf57fe303b5b8fa444d882fde

以下の様に、コンテナとして起動していることを確認できる。

[vagrant@fedora30 ~]$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS                 NAMES
adbb48def6a8  docker.io/library/nginx:latest  nginx -g daemon o...  25 seconds ago  Up 25 seconds ago  0.0.0.0:8080->80/tcp  elatedtaussig

ポッドとして扱うコマンドも用意されている。

[vagrant@fedora30 ~]$ podman pod ps
POD ID         NAME                STATUS    CREATED          # OF CONTAINERS   INFRA ID
475a420c00e7   elatedtaussig_pod   Running   37 seconds ago   2                 3659edba15a5

Podmanは サイドカーを実行できるか?

サイドカーを持つポッドのマニフェストを利用して、podman のロゴが象徴する複数のコンテナを一まとめにして動作させることができるか、確認してみる。
GitHubからサイドカーを持つポッドのマニフェストをクローンして、podman play kube filename で実行してみる。

[vagrant@fedora30 ~]$ git clone https://github.com/takara9/codes_for_lessons
[vagrant@fedora30 ~]$ cd codes_for_lessons/step07/sidecar/
[vagrant@fedora30 sidecar]$ ls
Dockerfile  contents-cloner  webserver.yml

次は、マニフェストのリストである。二つのコンテナ間は、emptyDir というストレージで連携する。

webserver.yml
## サイドカーポッドのサンプル
#
apiVersion: v1
kind: Pod
metadata:
  name: webserver
spec:
  containers:          ## メイン コンテナ
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: contents-vol
      readOnly: true

  - name: cloner       ## サイドカー コンテナ
    image: maho/c-cloner:0.1
    env:
    - name: CONTENTS_SOURCE_URL
      value: "https://github.com/takara9/web-contents"
    volumeMounts:
    - mountPath: /data
      name: contents-vol

  volumes:             ## 共有ボリューム
  - name: contents-vol
    emptyDir: {}

次は、podman play kube webserver.yml で実行した結果である。
残念ながら、サイドカーの中のコンテナを連携させるための 共有ボリュームで エラーが発生した。まだ、これからという感じだ。

[vagrant@fedora30 sidecar]$ podman play kube webserver.yml
Error: HostPath is currently the only supported VolumeSource

おそらく、共有ボリュームを必要としないタイプのサイドカーであれば、問題なく動作するであろう。しかし、その様な例は稀だと思う。

感想

Podman は、dockerコマンドを置き換える目的で、開発されている ルートレス、デーモンレスのコンテナ開発と実行環境である。また、その名前が示す様に、Kubernetesのポッドを実行できることも目指している。Red Hat が立ち上げたオープンソースプロジェクトであり、コミッターのリストをみると、Red Hatの社員が牽引している。そのためか、RHELよりも、Fedoraで最新のバージョンが利用できる。 また、様々な Linux Distribution にも対応すると宣言して、業界でよく知られたメジャーな存在となることを目指していることが伺われる。

個人的には、Dockerはコンテナの世界を幅広く世の中に知らしめ、コンテナの流通の仕組みを作るなど、IT業界への多大な貢献があるにも関わらず、どうして、ここまで置き換え様とされるのか、少々不敏な印象を受ける。 Dockerが非常に価値があることの裏返しでもあると思う。

これからのpodman の動向は注視していきたい。

その他の参考資料

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

Django2環境をDocker使って整える

はじめに

興味本位で新しいフレームワークを試してみようと始めた『Laravel環境構築

Docker構築にも慣れてきたので
改めてDjango2環境の開発環境としてDockerで作成してみました。

環境

  • Windows10 Pro
  • docker for windows (docker desctop community) (ver.2.1.0.2)
  • VSCode

Django2環境

Dockerの構成はこんな感じ

  • django2_nginx:1.17.3 (based nginx:1.17.3)
  • django2_python:3.7.4 (based python:3.7.4)
  • django2_postgres:9.6.15 (based postgres:9.6.15)

dockerの定義

ローカルのディレクトリ構成はこんな感じにしました。

├─ laravel/
   ├─ postgres/
   │  └─ Dockerfile       # postgres用Dockerfile
   ├─ nginx/
   │  ├─ etc/
   │  │  ├─ conf.d/
   │  │  │  └─ default.conf    # nginxサイト定義
   │  │  └─ nginx.conf          # nginx基本定義
   │  └─ Dockerfile               # nginx用Dockerfile
   ├─ python/
   │  ├─ apps/
   │  │  │ :
   │  │  └─ setup.sh    # migrate,createsuperuser用スクリプト
   │  └─ Dockerfile      # php-fpm用Dockerfile
   ├─ .gitignore           # pythonのキャッシュ除外用gitignore
   ├─ docker-compose.yaml  # 全てのdocker定義

docker-compose.yaml

全ての要、docker-compose.yamlはこんな形になりました。
ポートが微妙におかしいのは、先日のLaravevlと共存したいためです(笑)

  • nginxはポート8088でlistenしています。
  • nginxはdjango2プロジェクトのapps/static/opt/apps/staticに腹持ちさせました。
  • postgresは5432番でlistenしています。
  • postgresはデータ永続化のためdbvolumeコンテナを作成しました。
  • pythonは/opt/appsにdjango2プロジェクトをあらかじめ生成したものを腹持ちさせています。
  • Django2はgunicornによりnginxからの通信を3031番で待ち受けします。
docker-compose.yaml
version: '3.3'
services:
  postgres:
    container_name: django2_postgres
    build: ./postgresql/
    image: django2_postgres:9.6.15
    restart: always
    ports:
      - 5432:5432
    volumes:
      - dbvolume:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=sample_db
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres@1234
      - PGDATA=/var/lib/postgresql/data

  python:
    container_name: django2_python
    build: ./python/
    image: django2_python:3.7.4
    links:
      - postgres
    volumes:
      - ./python/apps:/opt/apps
      - ./python/app/static:/opt/apps/static
    expose:
      - 3031
    environment:
      - DJANGO_ADMIN_USER=admin
      - DJANGO_ADMIN_EMAIL=admin@localhost.localdomain
      - DJANGO_ADMIN_PASSWORD=django2@1234
    command: >
      /bin/bash -c
      "./setup.sh && 
       gunicorn wsgi -b 0.0.0.0:3031"
    depends_on:
      - postgres

  nginx:
    container_name: django2_nginx
    build: ./nginx/
    image: django2_nginx:1.17.3
    ports:
      - 8088:80
    links:
      - python
    depends_on:
      - python
    volumes:
      - ./python/app/static:/opt/apps/static

volumes:
  dbvolume:

それでは各Dockerの定義を見ていきましょう!

postgres:9.6.15用Docker定義

TZ変更のみのDockerfileとしています。

postgres/Dockerfile
FROM postgres:9.6.15

RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

nginx:1.17.3用Docker定義

TZ変更およびログファイルのstdout,strerrリンク、設定ファイルのCOPYをするDockerfileとしています。

nginx/Dockerfile
FROM nginx:1.17.3

RUN ln -sf /usr/share/zoneinfo/Japan /etc/localtime

RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
    ln -sf /dev/stderr /var/log/nginx/error.log && \
    ln -sf /dev/stdout /var/log/nginx/host.access.log

COPY ./etc/nginx.conf /etc/nginx/nginx.conf
COPY ./etc/conf.d /etc/nginx/conf.d

nginx.confの設定は、gzip、upstreamサーバ設定を行っています。

nginx/etc/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log debug;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    server_tokens off;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_types image/png image/gif image/jpeg text/javascript text/css;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_comp_level 9;

    upstream django2_server  {
        server python:3031 fail_timeout=0;
    }

    include /etc/nginx/conf.d/*.conf;
}

default.confの設定は割とシンプル

nginx/etc/conf.d/default.conf
server {
    listen       80;
    server_name  _;

    root /opt/apps;
    index index.php;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;

    location /static/ {
        root /opt/apps/static;
    }

    location / {
        try_files $uri @proxy_to_django2;
    }

    location @proxy_to_django2 {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
        proxy_pass http://django2_server;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\. {
        deny  all;
    }
}

python:3.7.4用Docker定義

TZ変更は他サーバーのDockerfileと同様ですが、
pythonモジュールのインストールをrequirements.txtにより指定し行っています。

WORKDIRはDjango2プロジェクトのappsフォルダとしています。

python/Dockerfile
FROM python:3.7.4

ENV APP_PATH /opt/apps

RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

WORKDIR $APP_PATH

COPY ./apps/requirements.txt $APP_PATH/

RUN pip install --no-cache-dir -r $APP_PATH/requirements.txt

インストールするモジュールは以下の通りです。
作成するプロジェクトに応じて追加してください。

python/apps/requirements.txt
django==2.2.5
djangorestframework
django-filter
psycopg2
gunicorn

このsetup.shによりDBのマイグレーションおよびスーパーユーザ作成を行っています。
ユーザ名、メールアドレス、パスワードはdocker-compose.yamlの環境変数で指定しています。

python/apps/setup.sh
#!/bin/bash

echo "##### setup django2 app #####"
echo "-> migrate database"
python manage.py makemigrations --noinput
python manage.py migrate --noinput

echo "-> create super user"
python manage.py shell <<EOF
from django.contrib.auth.models import User
if not User.objects.filter(username='$DJANGO_ADMIN_USER'):
    User.objects.create_superuser('$DJANGO_ADMIN_USER', '$DJANGO_ADMIN_EMAIL', '$DJANGO_ADMIN_PASSWORD')
    print('    create super user: $DJANGO_ADMIN_USER')
else:
    print('    user: $DJANGO_ADMIN_USER already exists, nothing to do')

pythonが動作した際に作成されるキャッシュ達をgitにcommmitしないためのおまじない(^^♪

python/.gitignore
__pycache__/
*.py[cod]

Dockerの起動

ここまで準備ができたらdockerを起動します。

C:\Users\tak>cd C:\Git\docker\django2
C:\Git\docker\django2>docker-compose build
C:\Git\docker\django2>docker-compose up

いやDockerによる開発環境、手軽に作れて壊せて便利ですね!

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

怖くないよね?マルチステージビルド

会社の本番環境をAWSのEKSに移行することになりその際にgolangのアプリを配布する際に使用したマルチステージビルドについて備忘録を交えながら記事を書いていきます。

先に言うんですけど

すみません僕Docker自体初めてです

今まで特に自分でDockerなどで環境構築をしたことがなかったのでこれが初めてのDocker作成です。
ほとんど分かっていないのでこいつダメやなって思いながら見てください

マルチステージビルドについて
https://github.com/moby/moby/pull/31257

簡単に言うと、fromでから作られた2つの複数のFROMイメージ間のファイルを COPY --from で直接を参照できるようになったのと AS で中間イメージに名前が付けられるようになったと言うものです。

golangってクロスコンパイルなどでシングルバイナリさえあればgolangの実行環境不要ですもんね
(golangにいては割愛します。)

早速やりましょうか

基本的なファイル構成はこちら

├build(ここにbuildの成果物が格納される)
│ └ appname(実行バイナリ)
├cmd(実行ディレクトリ)
│ └ main.go
├configs(設定ファイル関連)
├bitbucket-pipelines.yml
├.env(環境変数設定ファイル)
├docker-compose.yml
├Dockerfile
├go.mod
├go.sum
├Makefile(タスクランナー実行ファイル)

Makefile

基本的には今回は go build なども含めて全てMakefile側に任せています。

makefileに関しての設定はここで書きませんがちゃんとbuild配下にバイナリが入るように以下のように設定しました

build: 

@go build -ldflags="-w -s" -o build/appname ./cmd/main.go

これでmake buildのコマンドをターミナルで実行するとbuild配下にappnameと言うシングルバイナリが作成されます

Dockerfile

FROM golang:1.12.9 as builder

ADD . /appname/

WORKDIR /appname/

ENV GO111MODULE=on

COPY go.mod .
COPY go.sum .

RUN go mod download
COPY . .

RUN  CGO_ENABLED=0 GOOS=linux GOARCH=amd64 make build 

FROM alpine

RUN apk update \
  && apk add --no-cache

COPY --from=builder /appname/build /app/build

ENTRYPOINT [ "/app/build/appname" ]

まずポイントを解説すると

FROM golang:1.12.9 as builder

これでgolangのbaseimageを作成しますこの as builderと言うのがこの後にこのimageを渡すためのエイリアスになります

ENV GO111MODULE=on

COPY go.mod .
COPY go.sum .

RUN go mod download
COPY . .

go.modはgolangのモジュール関連の設定ファイルです(jsのpackage.jsonみたいなもの)
https://qiita.com/propella/items/e49bccc88f3cc2407745

ENV GO111MODULE=onはおまじないみたいなもので現行のgo1.13の環境では必要ないと思う(動かなかったらいれてください)

RUN  CGO_ENABLED=0 GOOS=linux GOARCH=amd64 make build 

ここでgoのbuildを行います make buildコマンドは先ほど作成した Makefileのトリガーとして buildを設定していたのでこのようなコマンドでタスクの実行が可能です

クロスコンパイルについてはこちらを参照してください
https://qiita.com/xshirade/items/abeb0d595be27cb6326e

FROM alpine

こちらはDockerの公式が提供している軽量なLinuxのイメージです。
https://alpinelinux.org/

COPY --from=builder /appname/build /app/build

ここで先ほどbuildした実行バイナリの格納ファイル等をこちらにCOPYしています
これでマルチステージビルドの完成です

補足

これでducker build などでもいいのですが開発環境等でmysqlに接続できる等などの確認が必要だと思うのでdokcer-compose.ymlで環境の構築を行います

docker-compose.yml
version: "3"

services:
  mysql:
    image: mysql:5.7.26
    container_name: db
    env_file:
      - .env
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
      - ./mysql/scripts/init:/docker-entrypoint-initdb.d
      - ./mysql/config:/etc/mysql/conf.d
  api:
    build: .
    depends_on:
      - mysql
    env_file:
      - .env
    ports:
      - "8080:8080"

volumes:
  db_data:

これで

$ docker-composer build && docker-compose up -d

こちらで接続ができているかなどの確認(go側にmysqlに接続などのプログラムは書いてくださいね)

最後に

僕自身初めてのDockerだったので探り探りでの実装だったのですがもし他にこれの方がいいよってものがありましたら是非教えて頂けますと幸いです。
最後まで読んで頂いてありがとうございました。

次にbitbucket-pipelines.ymlを使用したECRへのPUSHをしたいと思います。

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