- 投稿日:2019-07-14T21:11:48+09:00
Dockerでtabcmd実行環境を作る方法
Tableau Serverをコマンドラインから操作できる
tabcmd
ですが、Javaのバージョンが8以下でないとエラーが起るようです。(実際、Java12がインストールされた環境でtabcmdを実行するとエラーが起こります)
https://community.tableau.com/docs/DOC-22179そこで、Openjdk8をベースイメージにして、Dockerで
tabcmd
を実行できる環境を構築します。今回はDockerコンテナを起動し、
docker exec
でTableau Serverへのログイン、Publish、ログアウトをやってみます。環境
- mac Mojave 10.14.5
- Tableau Desktop 2019.2.1
- Tableau Server 2019.2.1
- tabcmd-2019-2-1
ディレクトリ構成
以下のディレクトリ構成にします。
tabcmd/ ├ docker-compose.yml ├ Dockerfile ├ sh └ publish.sh └ start.sh作成ファイル
Dockerfile
Openjdk8をベースイメージに、Dockerイメージを作成します。
curl
でtabcmd
を取得し、展開します。FROM openjdk:8 ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get install -y sudo curl gdebi # download tabcmd RUN curl -L -O https://downloads.tableau.com/esdalt/2019.2.1/tableau-tabcmd-2019-2-1_all.deb # extract deb RUN gdebi -n tableau-tabcmd-2019-2-1_all.debdocker-compose.yml
ローカルのsh/publish.shをDockerコンテナ上にマウントします。
docker-compose.ymlversion: '3' services: tabcmd: build: ./ tty: true container_name: tabcmd image: tabcmd volumes: - ./sh:/varsh/publish.sh
docker-compose.yml
で記載されている通り、Dockerコンテナ上にマウントされます。
引数を受け取り、Tableau Serverにログイン、Publish、ログアウトを実施します。publish.sh#!/bin/bash # set env path of tabcmd source /etc/profile.d/tabcmd.sh # login echo "starting login." tabcmd --accepteula login -s $1 --username $2 --no-certcheck --password $3 echo "completed login." # Publish echo "starting publish." tabcmd publish $4 -o $5 -r $6 --db-username $7 --db-password $8 --save-db-password --save-oauth --no-certcheck echo "completed publish." # logout echo "starting log out." tabcmd --accepteula logout -s $1 --no-certcheck echo "completed log out."start.sh
パラメータを設定し、ローカルで実行します。
ローカルのPublish対象のtwbファイルをDockerコンテナ上にコピーし、docker exec
によってDockerコンテナ上でスクリプトを実行します。start.sh#!/bin/bash # set param TABLEAU_SERVER_URL= TABLEAU_SERVER_LOGIN_ID= TABLEAU_SERVER_LOGIN_PASS= # tableau twb in local TWB_PATH_LOCAL= # in docker (ex. var/test.twb) TWB_PATH_DOCKER= OVERWRITE_WB_NAME= PJ_NAME= DB_USERNAME= DB_PASSWPRD= # copy from local to docker docker cp $TWB_PATH_LOCAL tabcmd:$TWB_PATH_DOCKER # exec publish on docker docker exec tabcmd bash -c "source var/publish.sh $TABLEAU_SERVER_URL $TABLEAU_SERVER_LOGIN_ID $TABLEAU_SERVER_LOGIN_PASS $TWB_PATH_DOCKER $OVERWRITE_WB_NAME $PJ_NAME $DB_USERNAME $DB_PASSWPRD"環境構築
上記のファイルを作成後、ローカルで
docker-compose.yml
と同一ディレクトリで以下を実行します。docker-compose up -d実行完了後、以下を実行してコンテナが起動していることを確認します。
docker ps結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 823a47830565 tabcmd "bash" About an hour ago Up About an hour tabcmdスクリプト実行
ローカルで
start.sh
と同一ディレクトリで以下を実行します。sh start.shこれでPublish完了です。
まとめ
Dockerを使うと環境間の差異が原因での実行エラーを防げます。
学習コストは高いですが、作業の標準化にはうってつけだと思います。
- 投稿日:2019-07-14T21:11:48+09:00
Dockerコンテナ上でtabcmd実行環境を作る方法
Tableau Serverをコマンドラインから操作できる
tabcmd
ですが、Javaのバージョンが8以下でないとエラーが起るようです。(実際、Java12がインストールされた環境でtabcmdを実行するとエラーが起こります)
https://community.tableau.com/docs/DOC-22179そこで、Openjdk8をベースイメージにして、Dockerで
tabcmd
を実行できる環境を構築します。今回はDockerコンテナを起動し、
docker exec
でTableau Serverへのログイン、Publish、ログアウトをやってみます。環境
- mac Mojave 10.14.5
- Tableau Desktop 2019.2.1
- Tableau Server 2019.2.1
- tabcmd-2019-2-1
ディレクトリ構成
以下のディレクトリ構成にします。
tabcmd/ ├ docker-compose.yml ├ Dockerfile ├ sh └ publish.sh └ start.sh作成ファイル
Dockerfile
Openjdk8をベースイメージに、Dockerイメージを作成します。
curl
でtabcmd
を取得し、展開します。FROM openjdk:8 ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get install -y sudo curl gdebi # download tabcmd RUN curl -L -O https://downloads.tableau.com/esdalt/2019.2.1/tableau-tabcmd-2019-2-1_all.deb # extract deb RUN gdebi -n tableau-tabcmd-2019-2-1_all.debdocker-compose.yml
ローカルのsh/publish.shをDockerコンテナ上にマウントします。
docker-compose.ymlversion: '3' services: tabcmd: build: ./ tty: true container_name: tabcmd image: tabcmd volumes: - ./sh:/varsh/publish.sh
docker-compose.yml
で記載されている通り、Dockerコンテナ上にマウントされます。
引数を受け取り、Tableau Serverにログイン、Publish、ログアウトを実施します。publish.sh#!/bin/bash # set env path of tabcmd source /etc/profile.d/tabcmd.sh # login echo "starting login." tabcmd --accepteula login -s $1 --username $2 --no-certcheck --password $3 echo "completed login." # Publish echo "starting publish." tabcmd publish $4 -o $5 -r $6 --db-username $7 --db-password $8 --save-db-password --save-oauth --no-certcheck echo "completed publish." # logout echo "starting log out." tabcmd --accepteula logout -s $1 --no-certcheck echo "completed log out."start.sh
パラメータを設定し、ローカルで実行します。
ローカルのPublish対象のtwbファイルをDockerコンテナ上にコピーし、docker exec
によってDockerコンテナ上でスクリプトを実行します。start.sh#!/bin/bash # set param TABLEAU_SERVER_URL= TABLEAU_SERVER_LOGIN_ID= TABLEAU_SERVER_LOGIN_PASS= # tableau twb in local TWB_PATH_LOCAL= # in docker (ex. var/test.twb) TWB_PATH_DOCKER= OVERWRITE_WB_NAME= PJ_NAME= DB_USERNAME= DB_PASSWPRD= # copy from local to docker docker cp $TWB_PATH_LOCAL tabcmd:$TWB_PATH_DOCKER # exec publish on docker docker exec tabcmd bash -c "source var/publish.sh $TABLEAU_SERVER_URL $TABLEAU_SERVER_LOGIN_ID $TABLEAU_SERVER_LOGIN_PASS $TWB_PATH_DOCKER $OVERWRITE_WB_NAME $PJ_NAME $DB_USERNAME $DB_PASSWPRD"環境構築
上記のファイルを作成後、ローカルで
docker-compose.yml
と同一ディレクトリで以下を実行します。docker-compose up -d実行完了後、以下を実行してコンテナが起動していることを確認します。
docker ps結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 823a47830565 tabcmd "bash" About an hour ago Up About an hour tabcmdスクリプト実行
ローカルで
start.sh
と同一ディレクトリで以下を実行します。sh start.shこれでPublish完了です。
まとめ
Dockerを使うと環境間の差異が原因での実行エラーを防げます。
学習コストは高いですが、作業の標準化にはうってつけだと思います。
- 投稿日:2019-07-14T20:12:20+09:00
Railsチュートリアルのために作成したDockerコンテナを起動し、必要なモジュールをインストールする for Windows
拙著RailsチュートリアルのためにDockerコンテナの作成 for Windowsの続きとなります。「Yay! You're on Rails!」と表示されるところまで持っていきます。
前回停止させたコンテナを再び起動
まず、前回停止させたDockerコンテナが存在することを確認します。
powershell$ docker container ls -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e11d56031051 ruby:2.5.1 "/bin/bash" 22 hours ago Exited (0) 21 hours ago RailsTutorialTest
STATUS
も、想定通りExited (0)
になっています。停止状態のDockerコンテナは、
docker start {コンテナ名}
コマンドで起動することができます。powershell$ docker start RailsTutorialTest RailsTutorialTest改めて
docker ls
コマンドを実行します。powershell$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e11d56031051 ruby:2.5.1 "/bin/bash" 22 hours ago Up About a minute 0.0.0.0:8080->3000/tcp RailsTutorialTest
RailsTutorialTest
コンテナが正常に起動されています。続いて、
RailsTutorialTest
コンテナのシェルに入りましょう。powershell$ docker container exec -it RailsTutorialTest /bin/bash root@e11d56031051:/#正常に
RailsTutorialTest
コンテナのシェルに入れました。
docker container exec
のオプション
- -it…ホスト側の標準入出力とDockerコンテナの標準入出力を接続する
- -i…ホスト側の標準入力とDockerコンテナの標準入力を接続する
- -t…Dockerコンテナの標準出力とホスト側の標準出力を接続する
- ホスト側からDockerコンテナ上のシェルを操作するために必要な設定
- コマンドを実行するコンテナの名前
- コンテナで実行するコマンド
- コマンドを実行するコンテナの名前の後に入力する
- 今回は
/bin/bash
であるRailsのインストール
bash# apt update # apt install -y nodejs # gem install rails -v 5.1.6aptリポジトリの一覧を更新
まずは
apt update
でaptリポジトリの一覧を更新します。リポジトリを追加・削除した場合には必須となる操作です。Node.jsのインストール
続いて、
apt install -y nodejs
でNode.jsをインストールします。
RailsではrubyのExecJS gemを使用し、ExecJS gemの実行にはJavaScriptランタイムが必要となるためです。CentOS 7.5にRuby on Railsチュートリアルの環境を構築するによると、JavascriptランタイムなしでExecJS gemを実行しようとした場合、以下のようなエラーが発生して実行できないそうです。
bash$ rails server /home/vagrant/.gem/ruby/gems/execjs-2.7.0/lib/execjs/runtimes.rb:58:in `autodetect': Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable) ...Rails本体のインストール
ここまで完了したら、いよいよRailsのインストールです。バージョンはRailsチュートリアルで使っている5.1.6を指定します。
bashSuccessfully installed rails-5.1.6ひとまずここまで到達できました。
Rails本体がインストールされていることの確認
bash# rails -v Rails 5.1.6
rails -v
コマンドにより、インストールされているRailsのバージョンを確認することができます。Rails 5.1.6が正しくインストールされているようです。gemをインストールするためにGemfileを修正する
bash# cd /var/www # rails _5.1.6_ new hello_app以下は、
rails-v
コマンドにより生成されたGemfileとRailsチュートリアルのリスト1.5に記載されていたGemfileの差分です。Gemfilesource 'https://rubygems.org' -git_source(:github) do |repo_name| - repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") - "https://github.com/#{repo_name}.git" -end - - -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.1.6' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' -# Use Puma as the app server -gem 'puma', '~> 3.7' -# Use SCSS for stylesheets -gem 'sass-rails', '~> 5.0' -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' -# See https://github.com/rails/execjs#readme for more supported runtimes -# gem 'therubyracer', platforms: :ruby - -# Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.2' -# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks -gem 'turbolinks', '~> 5' -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 2.5' -# Use Redis adapter to run Action Cable in production -# gem 'redis', '~> 4.0' -# Use ActiveModel has_secure_password -# gem 'bcrypt', '~> 3.1.7' - -# Use Capistrano for deployment -# gem 'capistrano-rails', group: :development +gem 'rails', '5.1.6' +gem 'puma', '3.9.1' +gem 'sass-rails', '5.0.6' +gem 'uglifier', '3.2.0' +gem 'coffee-rails', '4.2.2' +gem 'jquery-rails', '4.3.1' +gem 'turbolinks', '5.0.1' +gem 'jbuilder', '2.6.4' group :development, :test do - # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] - # Adds support for Capybara system testing and selenium driver - gem 'capybara', '~> 2.13' - gem 'selenium-webdriver' + gem 'sqlite3', '1.3.13' + gem 'byebug', '9.0.6', platform: :mri end group :development do - # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. - gem 'web-console', '>= 3.3.0' - gem 'listen', '>= 3.0.5', '< 3.2' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' + gem 'web-console', '3.5.1' + gem 'listen', '3.1.5' + gem 'spring', '2.0.2' + gem 'spring-watcher-listen', '2.0.1' end -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +# Windows環境ではtzinfo-dataというgemを含める必要があります gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]なお、この差分は、以下のコマンドにより取得したものをコピーアンドペーストしたものです。
powershell$ git --no-pager diff HEAD^..HEADbash# cd hello_app # bundle install最初の実行結果は、以下の通りになりました。
bashYou have requested: spring = 2.0.2 The bundle currently has spring locked at 2.1.0. Try running `bundle update spring` If you are updating multiple gems in your Gemfile at once, try passing them all to `bundle update`…おや、うまくいっていませんね。というわけで、以下のコマンドを実行してみます。
bash# bundle update何やら色々とインストールされていますね。最後に以下のメッセージが表示されるまで待ちます。
bashBundle updated!改めて、以下のコマンドを実行します。
bash# bundle install再び何やら色々と表示されましたね。最後に以下のメッセージが表示されるまで待ちます。
bashBundle complete! 15 Gemfile dependencies, 64 gems now installed. Bundled gems are installed into `/usr/local/bundle`
bundle install
が無事完了しました。Yay! You're on Rails!
bundle install
まで終われば、実際に動かすことができるRailsアプリケーションの作成は完了しています。RailsのローカルWebサーバー機能を使い、生成されたRailsアプリケーションを実際に動かしています。bash# rails server以下のメッセージが表示され、ローカルWebサーバーが起動されます。
bash=> Booting Puma => Rails 5.1.6 application starting in development => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.9.1 (ruby 2.5.1-p57), codename: Private Caller * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://0.0.0.0:3000 Use Ctrl-C to stopDockerコンテナ側の3000番ポートは、ホスト側の8080番ポートに連結されています。というわけで、ブラウザで
http://localhost:8080/
にアクセスしてみます。Yay! You're on Rails!…というわけで、無事Railsアプリケーションが動作するところまでの環境構築が完了しました。
演習
1. デフォルトのRailsページに表示されているものと比べて、今の自分のコンピュータにあるRubyのバージョンはいくつになっていますか? コマンドラインでruby -vを実行することで簡単に確認できます。
powershell$ ruby -v ruby 2.6.3p62 (2019-04-16 revision 67580) [x64-mingw32]上述の結果になりました。
2.6.3p62
でしょうか。2. 同様にして、Railsのバージョンも調べてみましょう。調べたバージョンはリスト 1.1でインストールしたバージョンと一致しているでしょうか?
powershell$ rails -v rails : 用語 'rails' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されませ ん。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してくだ さい。 発生場所 行:1 文字:1 + rails -v + ~~~~~ + CategoryInfo : ObjectNotFound: (rails:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundExceptionそもそもホストのWindows環境にRailsはインストールされていませんでした。
番外. Gemのバージョンを調べてみましょう。
powershell$ gem -v 3.0.2Gemのバージョンは
3.0.2
でした。関連リンク
- DockerでRailsチュートリアル(環境構築編) - 桜色HelloWorld - 行ったことは、ほぼこちらの後追いです。
- Rails 開発環境のバージョン確認 [自分用メモ] - Qiita - @dawn_628 さんによるQiita記事。3年以上前の記事ですが、コマンドラインの入力内容は現在も変わりありません。
- 投稿日:2019-07-14T17:27:35+09:00
Nginxとphp-fpmを用いてLaravalを表示する
どうも、若松です。
前回はLaravelをDockerで起動し、イメージを軽量化するところまで行いました。
https://qiita.com/t_wkm2/items/245288e42083ac7e4057今回は、
php artisan
でのサーバ起動ではなく、Nginx+php-fpmでLaravelを表示するところまでを行います。設定
ディレクトリ構造
docker/ ├─ docker-compose.yml ├─ nginx/ | ├─ Dockerfile | └─ default.conf └─ laravel/ └─ Dockerfiledocker-compose.yml
version: '2' services: nginx: image: nginx ports: - "80:80" laravel: image: laravelDockerfile(nginx)
FROM nginx:1.17-alpine # ローカルから設定ファイルをコピー COPY default.conf /etc/nginx/conf.d/default.confdefault.conf(nginx)
server { listen 80; server_name localhost; location / { # ドキュメントルート設定 root /var/www/laravel/public; fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$; fastcgi_intercept_errors on; fastcgi_index index.php; include fastcgi_params; # FastCGIの向き先をLaravelコンテナに設定 fastcgi_pass laravel:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }Dockerfile(laravel)
FROM amazonlinux:2 as vender # PHPインストール RUN amazon-linux-extras install -y php7.3 RUN yum install -y php-pecl-zip php-mbstring php-dom # Composerインストール RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" RUN php composer-setup.php RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composer # 環境変数設定 ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME "/opt/composer" ENV PATH "$PATH:/opt/composer/vendor/bin" # Laravelインストール RUN composer global require "laravel/installer" # Laravelプロジェクト作成 WORKDIR /var/www RUN composer create-project laravel/laravel laravel FROM php:7.3-fpm-alpine # ビルド用コンテナから必要なコンテンツをコピー COPY --from=vender --chown=www-data:www-data /var/www/ /var/www/操作
コマンドは全て最上位ディレクトリの
docker
から行う想定です。Nginxコンテナビルド
docker build nginx/. -t nginx --squashLaravelコンテナビルド
docker build laravel/. -t laravel --squashdocker-composeで起動
docker-compose upブラウザで表示を確認
http://localhost:8000 にアクセスすることで以下のサンプルを表示します。
解説
Nginxコンテナ
ベースイメージ
FROM nginx:1.17-alpineベースイメージにはNginx公式リポジトリにある
nginx:1.17-alpine
を使用しました。
2019/7/14現在のNginxの最新が1.17であり、軽量化を目的にAlpineLinux版を使いたかったためです。
80番ポートの開放やNginxの起動についてはベースイメージ内で既に設定されているため、今回のDokcerfileには記述していません。default.conf
COPY default.conf /etc/nginx/conf.d/default.conf設定はローカルに用意した
default.conf
をイメージにコピーして配置します。
FastCGI設定のほとんどは一般的な設定のため、特徴的なものだけ解説します。root
root /var/www/laravel/public;ドキュメントルートはLaravelコンテナのアプリケーションが配置されているディレクトリを指定します。
fastcgi_pass
fastcgi_pass laravel:9000;UnixソケットかTCPを指定できますが、Unixソケットではコンテナを越えられないため、TCPで設定します。
アドレスの指定にはDockerのNamespaceを利用します。Laravelコンテナ
前回のDockerfileからの差異のみ解説します。
ベースイメージ
FROM php:7.3-fpm-alpine実行用イメージのベースを
php:7.3-alpine
からphp:7.3-fpm-alpine
に変更しました。
これによってデフォルトでphp-fpmがインストールされた状態から設定を行えばよくなります。
9000番ポートの開放やphp-fpmの起動についてはベースイメージ内で既に設定されているため、今回のDokcerfileには記述していません。Laravelコンテンツのオーナー変更
COPY --from=vender --chown=www-data:www-data /var/www/ /var/www/
php:7.3-fpm-alpine
のphp-fpm初期設定では、php-fpmのワーカ起動ユーザはwww-data
になっています。
COPYコマンドで配置したLaravelコンテンツはrootがオーナーになってしまうため、そのままだと権限エラーとなります。
そこで、--chown
オプションを使用し、オーナーをwww-data
へ変更しています。
--chown
オプションはBashでいうところのchown -R
となるため、ディレクトリがあっても再帰的に処理してくれます。docker-compose
今回からコンテナが2つになったため、操作簡略のために
docker-compose
を導入しました。
docker-compose
には起動時のオプション設定や、複数コンテナのビルド、依存関係制御など様々な機能がありますが、ここではコンテナ起動/停止とポートオプションのみ使用しています。複数コンテナのビルドを使用しない理由
本当であれば使用したかったのが本音です。
しかしながら2019/7/14現在、BuildKitやsquashオプションに対応していないため、あえてdockerコマンドでビルドを行っています。Tips
コンテナイメージ内にあるファイルをローカルにコピーする
設定ファイルを作成する際に、デフォルトの設定をローカルにコピーし、それを改変して作成していくことはよくあると思います。
コンテナではSCPが使えないため、代わりにdocker cp
コマンドを使用します。
今回のdefault.confの場合は、以下のようにしてコピーしました。docker run -d --name nginx nginx:1.17-alpine docker cp $(docker ps --filter name=nginx -aq):/etc/nginx/conf.d/default.conf .コンテナイメージの履歴を確認する
FROMで使用するベースイメージには予めポートの開放やデーモンの起動が設定されている場合があります。
今回でいうところのNginxやphp-fpmですね。
それを確認するにはdocker history
コマンドを使用します。
例としてphp-fpmのhistoryを確認してみます。docker history --format {{.CreatedBy}} php:7.3-fpm-alpine /bin/sh -c #(nop) CMD ["php-fpm"] /bin/sh -c #(nop) EXPOSE 9000 /bin/sh -c #(nop) STOPSIGNAL SIGQUIT /bin/sh -c set -eux; cd /usr/local/etc; if… /bin/sh -c #(nop) WORKDIR /var/www/html /bin/sh -c #(nop) ENTRYPOINT ["docker-php-e… /bin/sh -c docker-php-ext-enable sodium ...このようにズラズラとコマンドが表示されるかと思います。
これは実行日次のtimestampが新しい順で上から並んでいます。
これを見るとベースイメージの最後に、9000番ポートの開放とphp-fpmの実行が行われているため、今回のDockerfileではポートの開放とデーモンの起動が不要なことがわかります。まとめ
Nginx+php-fpmに加えて、docker-composeも導入してみました。
そんなに特殊な設定を行ったわけではありませんが、Dockerfileの書き方やコンテナ特有の設定等はお伝えできたかと思います。
- 投稿日:2019-07-14T17:00:05+09:00
WordPress環境立ち上げるまでの最小ステップ
はじめに
過去に職場の環境として、業務上のナレッジマネジメントで使用するWikiとしてWordPressを使用していたことから、個人的にもWordPress環境の構築の勉強しようと思いたち、とりあえず何も投稿していないWordPressを立ち上げるところまで出来たので備忘録として投稿。
環境
- macOS Mojave 10.14.5
- HomeBrewインストール済み
- Dockerを過去の学習でインストール済み
HomeBrew install(導入済みなら不要)
ここを参照。
https://brew.sh/index_jaDocker install(導入済みなら不要)
この記事を参考にした。
https://qiita.com/nemui_/items/ed753f6b2eb9960845f7
けど以下だけでいけたような気がする。(遠い記憶)
$ brew cask install docker
ここから本題
Dockerを起動できてることは前提としておきます。
$ docker version
なり$ docker ps
がエラーにならなければOK。
$ docker pull mysql:5.7.26
しばらく待つ。
$ docker pull wordpress
またしばらく待つ。
両方完了したら$ docker run --name test-mysql -e MYSQL_ROOT_PASSWORD=test-pw -d mysql $ docker run --name test-wordpress --link test-mysql:mysql -d -p 8080:80 wordpress
$ docker ps
でtest-mysqlとtest-wordpressが立ち上がっていることが確認できたら
$ open http://localhost:8080/
を実行するとWordPressの言語設定画面が出てくるので言語を選択。
これでダッシュボードが表示されたら最低限の環境の立ち上げ完了。終わりに
brewの使い方とかdockerコマンドの意味とかは適宜確認してください。
コンテナ名とかPortとかは適宜変えたら良いです。
2019/7/14時点ではMySQLが8系だとWordPressが対応しておらずエラーが表示されるので、5系の最新を取ってくる必要があります。
面倒くさがってversion指定しなかったらローカルホストを表示した際にエラーが出てきて少しハマりました。
今回WordPress環境立ち上げようとググったりすると結構な確率でMAMPやXAMPが出てきたりして、バージョン管理が少々面倒だったり、新しくインストールして容量食わせたくなかったところから今回Docker使って立ち上げる方法を選択しました。(環境で書いたように元々Dockerはインストールしてたので)
そもそも自分がアプリ屋さんなのと、今はナレッジマネジメントでWordPressを業務で使っていないので、どんな立ち上げ方が主流なのかは知りませんが、MAMPやXAMP用意するよりDocker使えうほうが楽な気がしないでもない。
- 投稿日:2019-07-14T15:57:40+09:00
Docker/Kubernetes 実践コンテナ開発入門 part3
Dockerイメージの操作 には?
Dockerイメージを作る
docker image build
↓
作ったDockerイメージからDockerコンテナを作る
docker container run
↓
Dockerコンテナを動かしてアプリケーションを動かすDockerイメージのタグ とは?
Dockerイメージの名前に近い。Dockerイメージはタグを付けないとハッシュ値での管理になり、
手間がかかるのでタグを付けて管理することが多い。
タグの付け方は"名前空間/イメージ名/バージョン"Dockerコンテナの操作 には?
Dockerコンテナの状態は実行・停止・破棄の3種類。
docker container run
した直後は実行中の状態になる。処理を終了したコンテナは停止状態になるが、自動で破棄されることはない。
使わなくなったコンテナはどんどん破棄するのが良い。※破棄したコンテナと完全に同じコンテナは再現できない。
docker container run
dockerコンテナの作成と実行。
docker container run -d
デーモンとして実行。常駐させる。
docker container run -p
ポートフォワーディング。-p 9000:8080
と指定すれば、
ホスト側の9000番ポートがコンテナ側の8080ポートにつながる。docker container ls
現在実行中のDockerコンテナ一覧を表示する。
docker container ls -q
dockerコンテナの一覧のCONTAINER IDだけを表示する。
docker container rm
Dockerコンテナの破棄。
実行中のコンテナは-f
オプションをつけないと破棄できない。
docker container logs
Dockerコンテナの標準出力を表示する。-f
オプションで標準出力の取得をし続ける。
docker container exec
実行中Dockerコンテナでのコマンド実行。運用管理向けコマンド とは?
docker container prune
使われていないコンテナの一括廃棄。
docker image prune
イメージ版。Docker Composeでマルチコンテナを実行する には?
Docker Composeを使う。
yaml形式の設定ファイルを使って、複数のコンテナの実行を一括管理できる。Composeによる実行イメージ
$ docker container run -d -p 9000:8080 example/echo:latestこれと同じ内容をComposeに実行させてみる。
まずはyamlファイルを作成。docker-compose.ymlversion: "3" services: echo: image: example/echo:latest ports: - 9000:8080
docker-compose up -p
で実行する。
docker-compose down
で、yamlファイルで定義しているコンテナをすべて停止・削除できる。Composeによる複数コンテナの実行 には?
Jenkinsを使う。
Jenkins
継続的インテグレーションツール。
アプリケーションのコードが更新されたとき、自動的に環境のビルド・テストなどのデプロイ作業を実行する。jenkins使ってみる
docker composeを使ってjenkins環境を立てる。
使用したyamlファイルは以下。docker-compose.ymlversion: "3"↲ services:↲ master:↲ container_name: master↲ image: jenkinsci/jenkins:latest↲ ports:↲ - 8080:8080↲ volumes:↲ - ./jenkins_home:/var/jenkins_home↲"jenkinsci/jenkins:2.142-slim"ではうまく行かなかった。
$ docker-compose uplocalhost:8080でjenkinsの初期画面につながるようになるので、
ターミナルの途中で表示されてた初期パスワードで入る。jenkinsの初期設定する。すごいしょうもないミスで詰まってたんだけど、
ユーザー設定画面で適当なメールアドレスつけてたら進めなかった。
address@mail.comとかだと進めた。そこ弾くのね・・・
- 投稿日:2019-07-14T11:15:41+09:00
Docker/Kubernetes 実践コンテナ開発入門 part2
Dockerコンテナのデプロイ とは?
- Dockerイメージをビルドする = Dockerfileの通りにテンプレートとなるイメージを構築すること
コンテナでアプリケーションを実行する には?
まずはDockerイメージからDockerコンテナを生成する。
Dockerイメージ
Dockerコンテナを作成するために使用されるテンプレートとなるもの。
- コンテナを構成するファイルシステム
- 実行するアプリケーション
- コンテナの設定
などがまとめられている。公開されているものは
docker image pull "docker image name"
で取得可能。Dockerコンテナ
Dockerイメージから作成されるコンテナ。
具現化されたファイルシステムとアプリケーションが実行されている状態。
docker container run
でdockerイメージを実行することで作成できる。ポートフォワーディング
インターネットから特定のポート番号宛に届いたパケットを、予め設定しておいたLAN側の機器に転送する機能。
docker container run
の時にオプションでこの機能を設定する(-p 9000:8080
みたいな感じ)ことで、任意のポートからアプリケーションに到達できるようになる。ディレクトリ構成
docker -Dockerfile -main.goFROM golang:1.9 RUN mkdir /echo COPY main.go /echo CMD ["go", "run", "/echo/main.go"]DSL
ドメイン固有言語
FROM
Dockerイメージのベースとなるイメージの指定
まずこれをダウンロードしてからイメージをビルドする
イメージはDocker HubのレジストリにおいてあるRUN
Dockerイメージをビルドするときに、Dockerコンテナ内で実行するコマンド
今回はmkdir /echo
がコンテナ内で実行される
ビルド時のアプリケーションの更新や配置を行うCOPY
ホストマシン(俺のmacのこと)上にあるファイルやらディレクトリやらを
Dockerコンテナ内にコピーする
今回はmain.go
を/echo
ディレクトリにコピーしてるCMD
アプリを動かす時にコンテナ内で実行するプロセスを指定する
コンテナを動かす時にアプリケーションそのものを動作させる要するに
$go run /echo/main.go
をコンテナの中のシェルで実行してるようなもんmain.gopackage main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Println("received request") fmt.Fprintf(w, "Fuck You!!") }) log.Println("start server") server := &http.Server{Addr: ":8080"} if err := server.ListenAndServe(); err != nil { log.Println(err) } }
- HTTPリクエストが飛んできたら「Fuck You!!」とレスポンスしてくる
- 8080ポートでサーバアプリケーションとして動作する
- クライアントからのリクエストに対して「received request」と標準出力に表示する
簡単なDockerコンテナをビルドしてみる
Dockerfileのあるディレクトリで以下を実行する
$ docker image build -t example/echo:latest . Sending build context to Docker daemon 3.072kB Step 1/4 : FROM golang:1.9 ---> ef89ef5c42a9 Step 2/4 : RUN mkdir /echo ---> Running in 4796403a4857 Removing intermediate container 4796403a4857 ---> 7ee0156c2515 Step 3/4 : COPY main.go /echo ---> f0dcbce3f1df Step 4/4 : CMD ["go", "run", "/echo/main.go"] ---> Running in bdee6808b43e Removing intermediate container bdee6808b43e ---> 5e755d705882 Successfully built 5e755d705882 Successfully tagged example/echo:latestDockerfileに記述したコマンドが順に実行されている。
イメージリストを取得して、イメージが作成されているか確認する。$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE example/echo latest 5e755d705882 About a minute ago 750MBある。
Dockerコンテナを実行してみる
$ docker container run -d -p 9000:8080 example/echo:latest c3381624d1290b8052e78ac44ea05ad998095cbafbd33ed952441807c1c141e8-dオプションをつけてバックグラウンドで常駐させる。
また、-pオプションでポートフォワーディングしておかないとコンテナ外からアクセスできない。
この場合、ホスト側の9000番ポートをコンテナ内部の8080ポートにポートフォワーディング、つまり転送している。試しにcurlでリクエスト投げてみる。
$ curl http://localhost:9000/ Fuck You!!%無事にリクエストが帰ってきた。
実用的なコンテナの構築とデプロイ とは?
アプリケーションとコンテナの粒度 とは?
コンテナのポータビリティ とは?
Dockerフレンドリなアプリケーション とは?
永続化データをどう扱う?
コンテナ配置戦略 とは?
Swarmによる実践的なアプリケーション構築 とは?
Webアプリケーションの構成 とは?
MySQL Serviceの構築 には?
API Serviceの構築 には?
Nginxの構築 には?
Webの構築 には?
コンテナオーケストレーションによる開発スタイル とは?
Kubernetes入門 とは?
Kubernetesのデプロイ・コンテナ構築 とは?
Kubernetesの発展的な利用 とは?
コンテナの運用 とは?
より軽量なDockerイメージを作る とは?
Dockerのさまざまな活用方法 とは?
- 投稿日:2019-07-14T10:55:22+09:00
Docker で apt install -y がエラー "Unable to fetch some archives" で止まる
環境
Docker 18.09.7, build 2d0083d コンテナ ubuntu:18.04 状況
下のような Dockerfile でビルドしたイメージを久々にアップデートしようと思って
docker build -t <tag> .
を実行しました。DockerfileFROM ubuntu:18.04 ENV DEBIAN_FRONTEND noninteractive RUN set -x \ && rm -rf /var/lib/apt/lists/* \ && apt-get update \ && apt-get upgrade -y \ && apt-get install -y apt-utils RUN set -x \ && apt-get install -y make
apt-get install -y make
のところで、下記のようなエラーで止まってしまいました。E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/t/tzdata/tzdata_2019a-0ubuntu0.18.04_all.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm-common_2.4.95-1~18.04.1_all.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm2_2.4.95-1~18.04.1_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/l/linux/linux-libc-dev_4.15.0-52.56_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.95-1~18.04.1_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm-intel1_2.4.95-1~18.04.1_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm-nouveau2_2.4.95-1~18.04.1_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/libd/libdrm/libdrm-radeon1_2.4.95-1~18.04.1_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/m/mesa/libglapi-mesa_18.2.8-0ubuntu0~18.04.2_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/m/mesa/libgl1-mesa-dri_18.2.8-0ubuntu0~18.04.2_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/m/mesa/libglx-mesa0_18.2.8-0ubuntu0~18.04.2_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/m/mesa/libgl1-mesa-glx_18.2.8-0ubuntu0~18.04.2_amd64.deb 404 Not Found [IP: 91.189.88.162 80] E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?解決策
このようなエラーは一般的に
apt-get update
をかけることで解決するようですが、今回はイメージの再ビルドでキャッシュが使われてしまったため、アップデートが行われていなかったようです。コマンドに--no-cache
をつけて実行し直すと、先に進みました。docker build --no-cache -t <tag> .
- 投稿日:2019-07-14T09:56:00+09:00
Python ✖︎ Flask ✖︎ Webアプリ(3)Docker登場 DBの準備
目的
- Flask で使用する DB(PostgreSQL) を Docker を使用して準備する
- DB を pgadmin4 で見れるようにする
本編
ソースコード
環境準備
前回まで
Python ✖︎ Flask ✖︎ Webアプリ(2)HTMLの表示とメソッドとパラメータの受け取りかた
Python ✖︎ Flask ✖︎ Webアプリ(1)こんにちは世界Docker 環境準備
Mac の場合
brew cask install docker
ver 確認
$ docker -v Docker version 18.09.1, build 4c52b90フォルダ構成
$ tree . ├── README.md ├── docker-compose.yml ├── form.html ├── pgadmin ├── postgresql │ ├── data │ └── init │ └── 1_create_db.sql ├── requirements.txt └── src ├── main.py └── templates └── hello.htmlDB 作成
docker-compose.yml の作成
docker-compose.ymlversion: "3" services: postgresql: # イメージの指定 image: postgres:10.5 # コンテナの名前 container_name: flask_tutorial_postgresql # hostのport5432とコンテナのport5432を繋ぐ # ホスト;コンテナ ports: - 5432:5432 # hostとコンテナで共有するファイルやディレクトリを設定 # ホストのディレクトリ;コンテナのディレクトリ volumes: # /docker-entrypoint-initdb.dはコンテナ初回起動時に実行されるスクリプトを置く場所 - ./DB/init/:/docker-entrypoint-initdb.d # /var/lib/postgresql/dataはpostgresqlのデータが保存されている場所 - /var/lib/:/var/lib/postgresql/data # コンテナの環境変数設定 environment: # スーパユーザ名(省略時は"postgres") POSTGRES_USER: ${POSTGRES_USER} # スーパユーザのパスワード(省略時はパスワードなしでログイン可) POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # postgresqlの初期化時の文字コード POSTGRES_INITDB_ARGS: "--encoding=UTF-8" # ホスト名 hostname: postgres # Dockerを実行するユーザ user: root environment: TZ: "Asia/Tokyo" pgadmin4: image: dpage/pgadmin4:3.3 container_name: flask_tutorial_pgadmin4 ports: - 80:80 volumes: - ./pgadmin:/var/lib/pgadmin environment: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD} depends_on: - postgresql hostname: pgadmin4ポイント
${POSTGRES_USER}
や${POSTGRES_PASSWORD}
の${}
は変数を表していて
docker-compose.ymlと同じ階層にある.env
ファイルで変数を指定できる。.envの例
POSTGRES_USER=root POSTGRES_PASSWORD=root PGADMIN_DEFAULT_EMAIL=root PGADMIN_DEFAULT_PASSWORD=rootコンテナ操作
docker-compose.yml
があるディレクトリでdocker-compose up -d
実行コンテナ起動
$ docker-compose up -d Creating network "first_tutorial_default" with the default driver Creating flask_tutorial_postgresql ... done Creating flask_tutorial_pgadmin4 ... doneコンテナが起動できたか確認
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 487182403fc2 dpage/pgadmin4:3.3 "/entrypoint.sh" 8 seconds ago Up 6 seconds 0.0.0.0:80->80/tcp, 443/tcp flask_tutorial_pgadmin4 1441abbc6c72 postgres:10.5 "docker-entrypoint.s…" 9 seconds ago Up 7 seconds 0.0.0.0:5432->5432/tcp flask_tutorial_postgresqlコンテナを落とす
docker-compose.yml
があるディレクトリでdocker-compose down
実行$ docker-compose down Stopping flask_tutorial_pgadmin4 ... done Removing flask_tutorial_pgadmin4 ... done Removing flask_tutorial_postgresql ... done Removing network first_tutorial_default初回実行スクリプトについて
1_create_db.sqlcreate database flask_tutorial;ポイント
- ファイル名の先頭に数字を入れると、その順番で実行してくれる
- 1_DB作成
- 2_テーブル作成
- 3_初期データ挿入
みたいな
- 今回は単純に
flask_tutorial
というDBを作成しているのみDB 確認
pgadmin4にアクセス
docker-compose.ymlの一部抜粋pgadmin4: image: dpage/pgadmin4:3.3 container_name: flask_tutorial_pgadmin4 ports: - 80:80 volumes: - ./pgadmin:/var/lib/pgadmin environment: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD} depends_on: - postgresql hostname: pgadmin4コンテナ起動を起動した状態で
http://localhost:80
にアクセスすると下記の画面が表示される
ポイント
Email Address
とPassword
は.env で設定した値サーバ接続
pgadmin4にログインすると以下のように表示される。
Servers
を右クリック
Servers
>作成
>サーバ...
を選択すると以下が表示されるので設定していく
ポイント
ホスト名/アドレス
はホストのIPアドレスを調べて入力することDB確認
flask_tutorialというDBが存在していることを確認
躓いた所
- DBの初期化に失敗した場合(sql間違えたとか)はDB/dataのディレクトリを削除しないと、初期化が再度実行されない
次回
- flaskでDBに接続してみよう
- 投稿日:2019-07-14T09:15:14+09:00
Azureの仮想マシンで作ったDockerコンテナをラズパイに入れたい
高速な仮想マシンでコンテナを作って楽がしたい
DonkeyCarをやり始めて、早くも半年、インストールやコンパイルを繰り返していますが、
低速なラズパイでインストールに時間をかけるのが苦痛になってきました。人間はもっと生産的な仕事をするべきと、今更ながら思いました。
使ったことのないMicrosoft Azureをあれこれしていて、不毛に時間を使いました。
でも、やりたいことは、「仮想ラズパイマシンでDocker動かしてイメージ作れたらOKでしょ?」
これだけです。
仮想マシンを作る。
メモを書きながら実際にやってみます。
参考にしたのはこちら。
https://note.mu/kikuzokikuzo/n/na2e82c1c8835先達に感謝!
作成する仮想ラズパイマシンは
- 64bit ARM8プロセッサで動かす
- 32bit RaspbianOS (Stretch). BurstはDonkeyCarが不安定らしい dockerを動かしてイメージビルド(qemuによるエミュレーションを利用)
私はAzureで仮想マシンを作ってみます。
チュートリアルに従って、粛々と作ることとします。(コマンドラインでやるのは面倒なのでポータルでやります)
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/quick-create-portalあっさり出来上がり。Azure Cloud Shellでsshで接続。
色々入れてみるも、決め手に欠く
なぜか、インストールでパスがないなどの異常が出ますね。
この辺りも参考にしてみたけど、RaspberryPi仮想マシン作るの実は需要なのか?
というか、そもそも難しく考えすぎか?
要はARM64の環境を作って、Raspbianのstretchをインストールしたら良いのでは?http://matsujirushi.hatenablog.jp/entry/2018/04/15/214721
http://matsujirushi.hatenablog.jp/entry/2018/05/13/113219ちょっと方針変換。
http://innossh.hatenablog.com/entry/2018/06/22/170734
仮想マシン上で、ラズパイ仮想マシンを作り、その中でDockerを動かせばよろしいのでは?
Donkey CarにはDockerfileが入っていた
ハッカーばかりでドキュメントが(一部)不親切なDonkeyCarのリポジトリにDokerfileが入っていました。
浜松のunagi.piでDonkeyCarソースコードを読む勉強会に参加したところ、これを実際に動かすことに成功した人がいました。buildやcmakeの環境を色々考えると面倒ですが、Dockerfileからコンテナを作るだけなら行けそうです。
クラウドでインストールしても早くならない
https://www.slideshare.net/ShunsukeKikuchi1/raspberry-pi-147400803?from_m_app=ios
調べながらやっているうちに、実際にやって見た人発見。
どうやら浮動小数点演算をハードウェアでやっていないためと思われるスローダウンで、クラウドでやってもあまり高速にはならないそうだ。ちょっと目先を変える
64bitのラズパイ4とburstが出るまで待ってから、実際にやってみよう。
JETSONの方がクラウドコンパイルとは相性が良さそう。なので、raspberrypi4 + Azure を置いて、
JETSON nano + AWS で今から環境のセットアップをやってみることとします。
- 投稿日:2019-07-14T09:15:14+09:00
Azureの仮想マシンで作ったDockerコンテナをラズパイに入れたい(失敗)
高速な仮想マシンでコンテナを作って楽がしたい
DonkeyCarをやり始めて、早くも半年、インストールやコンパイルを繰り返していますが、
低速なラズパイでインストールに時間をかけるのが苦痛になってきました。人間はもっと生産的な仕事をするべきと、今更ながら思いました。
使ったことのないMicrosoft Azureをあれこれしていて、不毛に時間を使いました。
でも、やりたいことは、「仮想ラズパイマシンでDocker動かしてイメージ作れたらOKでしょ?」
これだけです。
仮想マシンを作る。
メモを書きながら実際にやってみます。
参考にしたのはこちら。
https://note.mu/kikuzokikuzo/n/na2e82c1c8835先達に感謝!
作成する仮想ラズパイマシンは
- 64bit ARM8プロセッサで動かす
- 32bit RaspbianOS (Stretch). BurstはDonkeyCarが不安定らしい dockerを動かしてイメージビルド(qemuによるエミュレーションを利用)
私はAzureで仮想マシンを作ってみます。
チュートリアルに従って、粛々と作ることとします。(コマンドラインでやるのは面倒なのでポータルでやります)
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/quick-create-portalあっさり出来上がり。Azure Cloud Shellでsshで接続。
色々入れてみるも、決め手に欠く
なぜか、インストールでパスがないなどの異常が出ますね。
この辺りも参考にしてみたけど、RaspberryPi仮想マシン作るの実は需要なのか?
というか、そもそも難しく考えすぎか?
要はARM64の環境を作って、Raspbianのstretchをインストールしたら良いのでは?http://matsujirushi.hatenablog.jp/entry/2018/04/15/214721
http://matsujirushi.hatenablog.jp/entry/2018/05/13/113219ちょっと方針変換。
http://innossh.hatenablog.com/entry/2018/06/22/170734
仮想マシン上で、ラズパイ仮想マシンを作り、その中でDockerを動かせばよろしいのでは?
Donkey CarにはDockerfileが入っていた
ハッカーばかりでドキュメントが(一部)不親切なDonkeyCarのリポジトリにDokerfileが入っていました。
浜松のunagi.piでDonkeyCarソースコードを読む勉強会に参加したところ、これを実際に動かすことに成功した人がいました。buildやcmakeの環境を色々考えると面倒ですが、Dockerfileからコンテナを作るだけなら行けそうです。
クラウドでインストールしても早くならない
https://www.slideshare.net/ShunsukeKikuchi1/raspberry-pi-147400803?from_m_app=ios
調べながらやっているうちに、実際にやって見た人発見。
どうやら浮動小数点演算をハードウェアでやっていないためと思われるスローダウンで、クラウドでやってもあまり高速にはならないそうだ。ちょっと目先を変える
64bitのラズパイ4とburstが出るまで待ってから、実際にやってみよう。
JETSONの方がクラウドコンパイルとは相性が良さそう。なので、raspberrypi4 + Azure を置いて、
JETSON nano + AWS で今から環境のセットアップをやってみることとします。
- 投稿日:2019-07-14T01:32:15+09:00
Dockerでデバッグ対象のコンテナにツールを入れずにtcpdump/straceなどを使うワンライナー
はじめに
Dockerであんなコンテナやこんなコンテナを動かしてると、なんかうまく動かなくて、デバッグのためにtcpdumpとかstraceなどのツールが使いたくなることが稀によくあります。
そんな時、デバッグ対象のコンテナ内にツールを一時的にインストールしちゃうというのが、まぁ簡単で分かりやすいんですが、デバッグ対象のコンテナを汚すのはできれば避けたいところです。Dockerのコンテナの分離というのは、結局のところLinuxのリソースの名前空間の分離であるので、逆に同じ名前空間を共有すれば、デバッグ用に立てた隣のコンテナから、デバッグ対象のコンテナのネットワークやプロセスの状態を観察することも可能です。
また、docker buildはDockerfileを標準入力から受け取ることもできるので、ワンライナーにしてデバッグ用のコンテナをシュッと呼び出せるようにしてみました。
TL;DR
結論だけ知りたい人はこちらをどうぞ。
<target>
のところはデバッグ対象のコンテナ名またはコンテナIDで読み替えて下さい。tcpdump
echo 'FROM alpine\nRUN apk add --no-cache tcpdump' \ | docker build -t debug -f - . \ && docker run -it --rm --net container:<target> debug tcpdump -nn -X port 80strace
$ echo 'FROM alpine\nRUN apk add --no-cache strace' \ | docker build -t debug -f - . \ && docker run -it --rm --pid container:<target> --cap-add sys_ptrace debug strace -fp 1ワンライナーでデバッグ用のツールをインストールして、デバッグ用のコンテナを立てる方法は、使いたいツールを変えればいろいろ応用が効くので、シェルのヒストリやスニペットに保存してシュッと呼び出すとよさそうです。
解説
環境
稼働確認した手元のDockerのバージョンは 19.03.0-rc2です。
$ docker version Client: Docker Engine - Community Version: 19.03.0-rc2 API version: 1.40 Go version: go1.12.5 Git commit: f97efcc Built: Wed Jun 5 01:37:53 2019 OS/Arch: darwin/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.0-rc2 API version: 1.40 (minimum version 1.12) Go version: go1.12.5 Git commit: f97efcc Built: Wed Jun 5 01:42:10 2019 OS/Arch: linux/amd64 Experimental: true containerd: Version: v1.2.6 GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb runc: Version: 1.0.0-rc8 GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f docker-init: Version: 0.18.0 GitCommit: fec3683事前準備
ここではデバッグ対象として、適当なnginxのコンテナをtargetという名前で起動しておきます。
$ docker run -it --rm -p 8080:80 --name target nginx:alpinetcpdumpを使ってみる
tcpdumpだけ入ったDockerfileを作って、debugというタグを付けてビルドします。
$ cat Dockerfile FROM alpine RUN apk add --no-cache tcpdump $ docker build -t debug . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM alpine ---> 3f53bb00af94 Step 2/2 : RUN apk add --no-cache tcpdump ---> Using cache ---> a000cadec8f5 Successfully built a000cadec8f5 Successfully tagged debug:latest
docker run --network container:<name|id>
で対象のコンテナのネットワークにアタッチできます。https://docs.docker.com/engine/reference/run/#network-settings
デバッグ用のコンテナをtargetのコンテナのネットワークにアタッチしつつ、tcpdumpを実行します。
$ docker run -it --rm --network container:target debug tcpdump -nn -X port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes試しに手元からcurlしてみると
$ curl http://localhost:8080/tcpdumpでパケットキャプチャできてることが分かります。
15:01:16.352790 IP 172.17.0.1.58354 > 172.17.0.2.80: Flags [S], seq 178914825, win 29200, options [mss 1460,sackOK,TS val 13258980 ecr 0,nop,wscale 7], length 0 0x0000: 4500 003c 56ed 4000 4006 8ba9 ac11 0001 E..<V.@.@....... 0x0010: ac11 0002 e3f2 0050 0aaa 0609 0000 0000 .......P........ 0x0020: a002 7210 5854 0000 0204 05b4 0402 080a ..r.XT.......... 0x0030: 00ca 50e4 0000 0000 0103 0307 ..P......... 15:01:16.352899 IP 172.17.0.2.80 > 172.17.0.1.58354: Flags [S.], seq 1290103227, ack 178914826, win 28960, options [mss 1460,sackOK,TS val 13258980 ecr 13258980,nop,wscale 7], length 0 0x0000: 4500 003c 0000 4000 4006 e296 ac11 0002 E..<..@.@....... 0x0010: ac11 0001 0050 e3f2 4ce5 69bb 0aaa 060a .....P..L.i..... 0x0020: a012 7120 5854 0000 0204 05b4 0402 080a ..q.XT.......... 0x0030: 00ca 50e4 00ca 50e4 0103 0307 ..P...P.....staceを使ってみる
同様にstraceをインストールしたDockerfileを用意してビルドします。
$ cat Dockerfile FROM alpine RUN apk add --no-cache strace $ docker build -t debug . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM alpine ---> 3f53bb00af94 Step 2/2 : RUN apk add --no-cache strace ---> Using cache ---> b357653376b3 Successfully built b357653376b3 Successfully tagged debug:lateststraceの場合は、
docker run --pid container:<name|id>
で対象のコンテナのPID名前空間にアタッチします。https://docs.docker.com/engine/reference/run/#pid-settings---pid
とりあえずpsを打ってみると、プロセスが見えてるのが分かります。
$ docker run -it --rm --pid container:target debug ps PID USER TIME COMMAND 1 root 0:00 nginx: master process nginx -g daemon off; 6 101 0:00 nginx: worker process 7 101 0:00 nginx: worker process 8 101 0:00 nginx: worker process 9 101 0:00 nginx: worker process 16 root 0:00 psただstraceを起動してみると、権限エラーが出ます。
$ docker run -it --rm --pid container:target debug strace -fp 1 strace: attach: ptrace(PTRACE_SEIZE, 1): Operation not permittedDockerはデフォルトではいくつかの特権操作は許可されておらず、 straceには
docker run --cap-add sys_ptrace
が明示的に許可が必要です。https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
$ docker run -it --rm --pid container:target --cap-add sys_ptrace debug strace -fp 1 strace: Process 1 attached rt_sigsuspend([], 8こんどはうまくstraceが起動できました。ためしに
nginx -s reload
でプロセスにシグナルを送ってみましょう。$ docker exec -it target nginx -s reload 2019/07/13 15:26:45 [notice] 87#87: signal process startedstraceでシステムコールトレースができてることが分かります。
strace: Process 1 attached rt_sigsuspend([], 8) = ? ERESTARTNOHAND (To be restarted if no handler) --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=87, si_uid=0} --- clock_gettime(CLOCK_REALTIME, {tv_sec=1563031605, tv_nsec=559042300}) = 0 rt_sigreturn({mask=[HUP INT QUIT USR1 USR2 ALRM TERM CHLD WINCH IO]}) = -1 EINTR (Interrupted system call) clock_gettime(CLOCK_REALTIME, {tv_sec=1563031605, tv_nsec=559133400}) = 0 clock_gettime(CLOCK_REALTIME, {tv_sec=1563031605, tv_nsec=559208800}) = 0 clock_gettime(CLOCK_REALTIME, {tv_sec=1563031605, tv_nsec=559260400}) = 0 uname({sysname="Linux", nodename="976678564bed", ...}) = 0 open("/etc/nginx/nginx.conf", O_RDONLY) = 3(参考) デバッグ用のイメージnicolaka/netshoot
毎回デバッグ用のツールをインストールするのがめんどくさければ、デバッグによく使うコマンドを全部入りしたnicolaka/netshootというDockerイメージがあります。
https://hub.docker.com/r/nicolaka/netshoot
何が入ってるかはDockerfileこれです。
https://github.com/nicolaka/netshoot/blob/master/Dockerfile
- apache2-utils
- bash
- bind-tools
- bird
- bridge-utils
- busybox-extras
- calicoctl
- conntrack-tools
- ctop
- curl
- dhcping
- drill
- ethtool
- file
- fping
- iftop
- iperf
- iproute2
- iptables
- iptraf-ng
- iputils
- ipvsadm
- libc6-compat
- liboping
- mtr
- net-snmp-tools
- netcat-openbsd
- netgen
- nftables
- ngrep
- nmap
- nmap-nping
- openssl
- py-crypto
- py2-virtualenv
- python2
- scapy
- socat
- strace
- tcpdump
- tcptraceroute
- util-linux
- vim
ちなみにREADMEに貼ってある、どのレイヤを調査するのにどのツールが必要かの画像の元ネタはこれのようです。まじすげーなこのサイト。
引用元: http://www.brendangregg.com/linuxperf.html
ワンライナーを組み立てる
まぁ仕事で使ってる環境に公式イメージじゃない野良のイメージを使うのも若干抵抗があるので、自分がよく使うものだけ適当に入れたイメージを作って使うのがよいとは思います。
ただ個人的にはイメージのメンテすらあまりしたくないので、オンデマンドでビルドして使う技も思いつきました。
docker buildはDockerfileを標準入力から受け取ることもできるので、 tcpdumpの例をワンライナーで書くとこんなかんじです。$ echo 'FROM alpine\nRUN apk add --no-cache tcpdump' \ | docker build -t debug -f - . \ && docker run -it --rm --net container:target debug tcpdump -nn -X port 80 Sending build context to Docker daemon 2.607kB Step 1/2 : FROM alpine ---> 3f53bb00af94 Step 2/2 : RUN apk add --no-cache tcpdump ---> Using cache ---> a000cadec8f5 Successfully built a000cadec8f5 Successfully tagged debug:latest tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytesstraceだとこんなかんじでしょうか。
$ echo 'FROM alpine\nRUN apk add --no-cache strace' \ | docker build -t debug -f - . \ && docker run -it --rm --pid container:target --cap-add sys_ptrace debug strace -fp 1 Sending build context to Docker daemon 2.607kB Step 1/2 : FROM alpine ---> 3f53bb00af94 Step 2/2 : RUN apk add --no-cache strace ---> Using cache ---> b357653376b3 Successfully built b357653376b3 Successfully tagged debug:latest strace: Process 1 attached rt_sigsuspend([], 8おわりに
ワンライナーでデバッグ用のツールをインストールして、デバッグ用のコンテナを立てる方法は、使いたいツールを変えればいろいろ応用が効くので、シェルのヒストリやスニペットに保存してシュッと呼び出すとよさそうです。
これであんなコンテナやこんなコンテナをデバッグし放題ですねー。
- 投稿日:2019-07-14T01:13:00+09:00
Docker Private Registryのtagとrepositoryを削除する方法
ヘッダーにAccept: application/vnd.docker.distribution.manifest.v2+jsonを追加して、Get /v2/<イメージ名>/manifests/<タグ>でマニフェストを取得(https://docs.docker.com/registry/spec/api/#pulling-an-image)
レスポンスのヘッダーに付いてくる[Docker-Content-Digest]を確認。
Delete /v2/<イメージ名>/manifests/の実行。
registryコンテナ本体でbin/registry garbage-collect /path/to/config.ymlを実行してガーベッジコレクションを起動。
https://docs.docker.com/registry/garbage-collection/対象のrepositoryディレクトリを手動削除。
準備
Amazon Linux release 2 (Karoo)
# amazon-linux-extras install -y docker=18.03.1のようにバージョン指定でインストールも可能 $ sudo amazon-linux-extras install -y docker # dockerサービス起動 $ sudo systemctl start docker # DockerはUnixソケットをTCPポートにバインドするため、 # rootユーザーでしか動作しません。sudoコマンドを # 使いたくないという場合は、dockerグループを作成して # そこにユーザーを追加してください # なお、sudoコマンドでdockerコマンドを実行できるように # するには、dockerグループにユーザー追加後にログオフして # 再度ログインする必要があります $ sudo usermod -a -G docker $USER # 確認コマンド $ cat /etc/group | grep docker # dockerサービスの自動起動を有効にする $ sudo systemctl enable docker# Docker Private Registryコンテナ起動 $ docker run -d --name testreg \ -e REGISTRY_STORAGE_DELETE_ENABLED=true \ -p 5000:5000 registry:2 # Docker Private Registryにalpineのイメージを登録 $ docker pull alpine:latest $ docker tag alpine:latest 127.0.0.1:5000/myrepo:tag1 $ docker push 127.0.0.1:5000/myrepo:tag1 # 全てのカタログとタグのリスト取得 $ curl http://127.0.0.1:5000/v2/_catalog {"repositories":["myrepo"]} # 対象のタグリスト取得 $ curl http://127.0.0.1:5000/v2/myrepo/tags/list {"name":"myrepo","tags":["tag1"]} # 対象のタグ削除 $ digest=$(curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -sI http://127.0.0.1:5000/v2/myrepo/manifests/tag1 | grep Docker-Content-Digest | tr '\r\n' ' ' | awk '{print $NF}') $ curl -X DELETE "http://127.0.0.1:5000/v2/myrepo/manifests/$digest" # 対象のタグ削除確認 $ curl http://127.0.0.1:5000/v2/myrepo/tags/list {"name":"myrepo","tags":null} # config.yml作成 $ sudo mkdir /etc/docker/registry $ sudo vi /etc/docker/registry/config.yml/etc/docker/registry/config.ymlversion: 0.1 storage: filesystem: rootdirectory: /var/lib/registry# ガーベッジコレクション実行 # マニフェストによって参照されなくなったファイルシステムからBLOBを削除 $ docker exec -it testreg registry garbage-collect /etc/docker/registry/config.yml 0 blobs marked, 3 blobs and 0 manifests eligible for deletion blob eligible for deletion: sha256:57334c50959f26ce1ee025d08f136c2292c128f84e7b229d1b0da5dac89e9866 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/57/57334c50959f26ce1ee025d08f136c2292c128f84e7b229d1b0da5dac89e9866 go.version=go1.11.2 instance.id=8c036012-29fa-42a4-bdd8-e228153fbfba service=registry blob eligible for deletion: sha256:b7b28af77ffec6054d13378df4fdf02725830086c7444d9c278af25312aa39b9 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/b7/b7b28af77ffec6054d13378df4fdf02725830086c7444d9c278af25312aa39b9 go.version=go1.11.2 instance.id=8c036012-29fa-42a4-bdd8-e228153fbfba service=registry blob eligible for deletion: sha256:0503825856099e6adb39c8297af09547f69684b7016b7f3680ed801aa310baaa INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/05/0503825856099e6adb39c8297af09547f69684b7016b7f3680ed801aa310baaa go.version=go1.11.2 instance.id=8c036012-29fa-42a4-bdd8-e228153fbfba service=registry # Docker Private Registryのコンテナ再起動 $ docker restart testreg # repositoriesディレクトリ確認 $ docker exec -it testreg ls /var/lib/registry/docker/registry/v2/repositories myrepo # 対象のrepositoriesディレクトリを削除 $ docker exec -it testreg rm -rf /var/lib/registry/docker/registry/v2/repositories/myrepo # 全てのカタログとタグのリスト取得 $ curl http://127.0.0.1:5000/v2/_catalog {"repositories":[]} # 対象のタグリスト取得 $ curl http://127.0.0.1:5000/v2/myrepo/tags/list {"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known to registry","detail":{"name":"myrepo"}}]}