- 投稿日:2019-11-26T23:59:48+09:00
バイオインフォ(に限らないけど)の人が docker for Mac で、よくひっかかるところ
バイオインフォ(に限らないけど)の人が docker for Mac で、よくひっかかるところ
よく聞くので、記事にしてみました。
最初に
この記事は、Workflow Advent Calendar 2019 - Qiita と、バイオインフォマティクス Advent Calendar 2019 - Qiita の5日目の記事です。
内容
Mac上に、CPUもメモリも十分あるのに、なぜかエラーになる問題
他の環境で実行したところ、CPUは1コアしか使わないし、メモリも
4GB
もあれば十分、自分の Mac には8GB
のメモリがあるので、問題なく動くはず。
しかし実行すると動かない。このようなケースの
解決策、 Docker for Mac のメモリ設定を見直す
Docker for Mac の設定で、メモリの割当が2GBがデフォルトだったかなとおもいます。
なので、それを引き上げてあげれば解決することが多いです。この問題は、だいたい1度解決すると、ずっと発生しないのですが、
新しく買い替えたとき
に再度発生することがあるようです。困っている人がいたら、以下のように聞いてあげると良いかもしれません。
Macじゃなくて、Docker for Mac のメモリの割当はいくつになっていますか?Mac で動いていた、別環境の Linux で実行したら、自分で消せないファイルができる問題
解決策、-u $(id -u):$(id -g) をつけて実行してみる。
ざっくりいうとMac 上では、dockerで生成したファイルは、自分のユーザの権限でMac上にできあがります。
Linuxに持っていったら場合に、消せないファイルができるというのは、
root
権限で、ファイルが出来上がってしまうということで、自分の権限では消せないということが発生します。その場合は、実行するときに、 docker の
-u
オプションで、自分のUID
とGID
を指定してあげるとよいとおもいます。消せなくなったファイルについては、別コンテナを立ち上げて消して上げればよいのではないかと思います。
- 投稿日:2019-11-26T23:50:56+09:00
Rails + TypeScript + Swagger 環境をDockerで爆速で構築する
なにこの記事
単純にdcoker-composeを使って、フロントとWEB APIを分けて、ついでにAPIをSwaggerで管理するテンプレートの紹介と、テンプレート作るまで手順を書いたザックリとした記事です。
たぶん爆速でできる、はず。テンプレート
こちらのリポジトリからクローンしてください。
./qs init
で環境整うので、あとはhttp://localhost:8080
にアクセスすると、こんな感じで簡単なWEBアプリが作られてます。Swaggerを利用する際は、
./qs up doc
した後で、http://localhost
にアクセスするとAPIドキュメントを利用できます。テンプレート作成までの手順
ここからはどうやって上記のテンプレート作ったかの手順を説明していきます。
構成
docker-composeのサービス構成としては下記のようにしました。
webがフロントエンドでTypeScriptにて処理を行います。
apiがWEB APIでRuby on Railsで作られてます。
フロントも含めて全てRailsで記述できますが、今回はフロントとAPIのプラットフォームが別という想定で構築しました。
APIドキュメントはSwaggerがイメージを配布してたのでサービスを分けました。docker-compose.ymlversion: '3' services: db: image: postgres ports: - "5432:5432" volumes: - data:/var/lib/postgresql/data:cached api: build: ./api command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./api:/app:cached - bundle:/usr/local/bundle:cached environment: HOME: /app RAILS_ENV: development ports: - "3000:3000" tty: true links: - db web: build: ./web command: npm start volumes: - ./web:/app:cached environment: NODE_ENV: development ports: - "8080:8080" tty: true links: - api doc: image: swaggerapi/swagger-ui volumes: - ./api.yml:/usr/share/nginx/html/api.yml environment: API_URL: api.yml ports: - "80:8080" volumes: bundle: driver: local data: driver: localディレクトリ構成は以下のようにしてます。各フォルダ配下にDockerfileを配置して、プロジェクトフォルダ直下のdocker-composeから管理しています。
projects # プロジェクトフォルダ - api # Railsのソースを配置 - Dockerfile - Gemfile - web # TypeScriptのソースを配置 - Dockerfile - package.json api.yml # Swagger定義 docker-compose.ymlそれでは各サービスの構築手順を解説していきます。
API
まずはAPIを立ち上げましょう。とは言っても簡単です。
コマンド打っただけで簡単に構築できました。やっぱりRailsって便利ですね。アプリの立ち上げ
DockerfileとGemfileを配置して、下記のコマンドを実行していきます。
http://localhost:3000
にアクセスしてRailsのウェルカムページが表示されれば完了です。$ docker-compose build api $ docker-compose run --rm api bundle install $ docker-compose run --rm api bundle exec rails new . -f -d=postgresql --api $ docker-compose run --rm api bundle update # database.ymlを下記の内容で手動で書き換える $ docker-compose run --rm api bundle exec rails db:create $ docker-compose up apidatabase.ymldefault: &default adapter: postgresql encoding: utf8 min_messages: WARNING host: db port: 5432 username: postgres password: postgres pool: 5 timeout: 5000 stats_execution_limit: 10 development: <<: *default database: development test: <<: *default database: test production: <<: *default database: productionDockerfile
# use ruby version 2.6.5 FROM ruby:2.6.5 # using japanese on rails console ENV LANG C.UTF-8 # remove warn ENV DEBCONF_NOWARNINGS yes ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE yes ENV XDG_CACHE_HOME /tmp EXPOSE 3000 # install package to docker container RUN apt-get update -qq && apt-get install -y \ build-essential \ libpq-dev \ vim \ less # install yarn RUN apt-get install apt-transport-https RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update && apt-get install -y yarn # install nodejs RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - RUN apt-get install -y nodejs # setting work directory RUN mkdir /app WORKDIR /app # setting environment value ENV HOME /app # executing bundle install COPY Gemfile /app/GemfileGemfile
source 'https://rubygems.org' gem 'rails', '~> 5.2.3'エンドポイントの追加
文字列フィールドを1つもつModelのAPIを追加します。下記のコマンド打てば、API一式とテストを作ってくれます。素晴らしいいい。
Rspecを使うのでGemfileにgemを追加しておいてください。$ docker-compose run --rm api bundle exec rails g scaffold Content body:string $ docker-compose run --rm api bundle install $ docker-compose run --rm api bundle exec rails g rspec:install $ docker-compose run --rm api bundle exec g rspec:integration Contentこれでほぼ完成ですが、なぜかapiフラグをつけるとストロングパラメーターを使わないので、下記のようにコントローラーを修正します。
contents_controllers.rbdef content_params params.require(:content).permit(:body) endあとは、適宜取得したいようにController、Modelの修正と、テストの追加はしておいてください。
面倒なんでここでは割愛します。リポジトリのコミットログ見てください。rack_corsの導入
このままだとフロントからアクセスできないので、rack_corsを導入します。
Gemfileにrack-cors
を追加して、docker-compose run --rm api bundle install
してください。
そして、下記の修正をconfig/application.rb
に追記すれば完成です。config/application.rbconfig.middleware.insert_before 0, Rack::Cors do allow do origins 'localhost:3000', 'localhost:8080' resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options] end end疎通確認
これだけでAPIの構築が完了しました。最後に疎通確認を行います。
RailsコンソールからContentモデルに適当にデータを登録して、ブラウザからhttp://localhost:3000/contents
を叩いて見ましょう。[ { "id": 1, "body": "hoge", "created_at": "2019-11-22T15:54:26.543Z", "updated_at": "2019-11-22T15:54:26.543Z" }, { "id": 2, "body": "foo", "created_at": "2019-11-22T15:54:30.464Z", "updated_at": "2019-11-22T15:54:30.464Z" } ]無事に取得できました。これでAPIの作成は終了です。
フロント
実際にユーザーがアクセスして使うフロントアプリケーションを作成します。
React、VueなどJSフレームワークを使ってもいいのですが、今回は超小さいアプリなのでTypeScriptを使ってサクッと作ろうかと思います。アプリの立ち上げ
apiと同じようにDockerfileとpackage.jsonを配置して、下記のコマンドを実行していきます。
$ docker-compose build web $ docker-compose run --rm web npm installurlとかは適宜変えてください。パッケージは今回使うものを記載してあります。
package.json{ "name": "web", "version": "1.0.0", "description": "web app", "main": "index.js", "scripts": { "start": "http-server -o", "tsc": "tsc", "build": "webpack" }, "repository": { "type": "git", "url": "git+https://github.com/belion-freee/rails_web_api.git" }, "author": "belion-freee", "license": "ISC", "bugs": { "url": "https://github.com/belion-freee/rails_web_api/issues" }, "homepage": "https://github.com/belion-freee/rails_web_api#readme", "devDependencies": { "axios": "^0.19.0", "http-server": "^0.11.1", "ts-loader": "^6.2.1", "typescript": "^3.7.2", "webpack": "^4.41.2", "webpack-cli": "^3.3.10" } }処理の記述
TypeScriptは初めてでしたので、下記の記事を参考にして作成しました。
https://qiita.com/EBIHARA_kenji/items/31b7c1c62426bdabd263
API通信のために axios
Webサーバーとして立ち上げるために http-server
をそれぞれ使ってます。
tsconfig.json
がTypeScriptの設定を記述するファイルです。自分は下記のように設定しました。もっといろんな設定ができるので公式リファレンスを読んでみてください。tsconfig.json{ "compilerOptions": { "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "outDir": "./build", /* Redirect output structure to the directory. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "strict": true, /* Enable all strict type-checking options. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "include": [ "src/**/*.ts" ], "exclude": [ "node_modules", "**/*.spec.ts" ] }ソースコード
ここからは実際のソースコードです。下記のように記述しました。
index.html
を用意して、DOMに要素を動的にjsで展開して行く構成です。index.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="./style.css"> <title>TS-Web</title> </head> <body> <h1>This is the template of Web APP</h1> <h2>created by TypeScript</h2> <h3>Those are contents from Web API</h3> <div id="contents-form"> <form> <input type="text" value="" id="content-body"> <button type="button" class="add-content">Add</button> </form> </div> <div id="contents"></div> <script src="./build/index.js"></script> </body> </html>
src
ディレクトリ配下にindex.html
を操作するjsファイルを配置します。
index.ts
: indexを操作するためのjs。api.ts
: Rails-APIと通信するための機能を備えたクラス。https://github.com/belion-freee/rails_web_api/tree/master/web/src
ビルド
ここまで作成したら次にビルドする必要があります。ビルドにはwebpackを仕様します。すでにインストール済みなので、コマンドを実行してビルドしましょう。
$ docker-compose run --rm web npm run build
build
ディレクトリにソースが作成されていれば成功です。
ここまででフロントの実装は終了です。APIドキュメント
次にAPIドキュメントを作成します。とは言ってもすごい簡単です。
プロジェクト配下に
api.yml
を配置します。サンプルは公式から拝借しました。
https://github.com/swagger-api/swagger-samples/blob/master/java/inflector-dropwizard/src/main/swagger/swagger.yaml内容はこんな感じです。
https://github.com/belion-freee/rails_web_api/blob/master/api.yml記述に関しては、API自体がシンプルなのもありますが、ドキュメント読まなくてもなんとなく書けるくらい分かり易かったです。
記述が終わったら、
docker-compose up doc
してhttp://localhost
にアクセスすると読めるので、記述が正しいか確認してください。
これで全ての工程が終了です。まとめ
いかがだったでしょうか。
API関連はすごい簡単に導入できましたが、TypeScriptはちょっと時間がかかりました。
TypeScriptに関してはもっとちゃんと書きたいなと思います。だいぶやっつけ感ある。それでも、ものすごい早く複数プラットフォームのミニマムなWEBアプリを開発できたので、Dockerさんに感謝です。
流石にミニマムすぎるので、暇なときにAPI認証のエンドポイントを実装したいと思います。
- 投稿日:2019-11-26T20:18:13+09:00
【Docker/Kubernetes】今夜勝ちたいKubernetes概要
この投稿ではインストールを求めたりばかげた呪文を入力させたりはしない。
コンテナオーケストレーションシステムである"Kubernetes"。
dockerを覚えたうえでなぜそんなものまで覚えなければならないのか、
現在まで勉強した結果を私なりにまとめよう。(途上につき、間違いなどあれば申し訳ありません。ご指摘いただけると幸いです)
なぜKubernetesが必要か
一言でいえば、運用、特に複数台のホストにまたがるサービス運用において課題が出るからと言えます。
dokcer-composeによる複数コンテナを管理でローカルの開発環境についてはほぼ問題はないと思います。
しかし、これらは基本的に開発マシンなどといった1つのホスト内での話です。実運用においては例えば以下のような課題を考慮し、複数ホスト間での連携も必要となってきます。
- ロードバランシング
- デプロイ時のダウンタイム
- オートスケーリング
- 死活監視(ホスト内のコンテナについて)
しかし、その構築は非常に複雑なものとなります。
こういった複数ホスト、コンテナ間の連携や、サービス実運用に必要な機能をもたらすのがKubernetesとなります。
読み飛ばしてもいいところ
例えばオートスケーリングについて考えてみます。
nginx、phpアプリ、mysqlコンテナが一つずつ稼働しているホストがあり、そのスケールが必要になったとします。
このホストそのものを単純にスケールしてよいものでしょうか?効率的な運用を考えれば、ホストを増やしたうえでそれぞれのホストにどうコンテナをデプロイするか考える必要が出てきそうです。
死活監視についてもそうです。ホストそのものならまだしも、
ホスト内で動いているコンテナすべての死活監視、および必要に応じた自動起動を自前で構築しようとすると難しいのではないでしょうか。構成
以下大体の構成。デプロイメントあたりから脳が若干受付拒否をしだす。
- クラスタ:以下に挙げるdockerホストなどのリソース集合体
- マスターノード:管理サーバ
- ノード(Node):実際にコンテナがデプロイされるホスト
- ネームスペース(NameSpace):クラスタ内の仮想的なクラスタ
- ポッド(Pod):コンテナの集合(同一ポッド内のコンテナはノードを跨がない)
- レプリカセット(ReplicaSet):ポッドの複製・管理
- デプロイメント(Deployment):レプリカセットの世代管理
- サービス(Service):ポッドの集合&ポートなどの通信規約(書いて字の如くこの単位で一つのサービス)
- イングレス(Ingress):サービスの公開&ルーティング
という感じです。フワッと理解できたら今日はもう優勝して大丈夫です。
- 投稿日:2019-11-26T20:03:17+09:00
TerraformとSAMでAWSリソースを用意する人のための実行環境をdockerで作るよ
下記をDockerfileとしてLinux上に用意してください。
FROM python:3.8 as baseimage RUN pip install \ awscli \ aws-sam-cli # terraformバージョン指定 ARG terraform_version="0.12.16" WORKDIR /root/ ADD https://releases.hashicorp.com/terraform/${terraform_version}/terraform_${terraform_version}_linux_amd64.zip ./ RUN unzip /root/terraform_${terraform_version}_linux_amd64.zip -d /usr/bin/ \ && chmod +x /usr/bin/terraform # -------------------------------------------------- FROM python:3.8-alpine3.10 # pip installed commands COPY --from=baseimage /usr/local/bin/aws* /usr/local/bin/ COPY --from=baseimage /usr/local/bin/sam /usr/local/bin/ COPY --from=baseimage /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages # terraform COPY --from=baseimage /usr/bin/terraform /usr/bin/ USER root RUN apk upgrade ## 使用コマンド RUN apk add \ vim \ less \ jq \ git \ groff # JST化 RUN apk --no-cache add tzdata \ && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ && apk del tzdata下記コマンドでビルドします。
docker build -t awssamterraform . --no-cache
下記コマンドでコンテナの中に入ります。
docker run -it awssamterraform ash
- 投稿日:2019-11-26T19:56:14+09:00
OpenShiftによるJava EEアプリケーションのモダナイゼーションをやってみた(4)
2019年12月中旬に公開予定の連載記事と連動した自習用コンテンツです。記事作成にQiitaの公開用URLが必要なため、事前に投稿しました。この投稿の全文は記事公開と同時に公開します。
はじめに
IBMのCode Patternsの1つである架空の医療会社のExample HealthのOpenShiftによるJava EEアプリケーションのモダナイゼーションの4回目の投稿です。
これまでの投稿では、架空の医療会社のExample HealthはJava EEアプリケーションのモダナイゼーションに成功しました。OpenShiftに移行した結果、容易に機能拡張できようになりシステムを拡大して新しいサービスを追加していきます。
OpenShiftによるJava EEアプリケーションのモダナイゼーションをやってみた。
ビジネスロジック用のOpen Libertyで実行されているJava EEアプリケーションのモダナイゼーションOpenShiftによるJava EEアプリケーションのモダナイゼーションをやってみた(2)
患者用UI(ユーザーインターフェイス)のモダナイゼーションOpenShiftによるJava EEアプリケーションのモダナイゼーションをやってみた(3)
健康記録管理者用のPHPアプリケーションの機能追加順風満帆に見えたExample Healthですが、ある問題に直面します。
ある問題を解決することが4回目の投稿のメインテーマになります。お楽しみに
- 投稿日:2019-11-26T19:33:53+09:00
3分28秒でDjangoをデプロイ(docker-compose)
既に作成されたプロジェクトの場合でも対応可能な形のdocker-composeを作成しましたので、仕様を記事にまとめます。
GitHub上にHowtoUseを書いておりますのでどうぞ→GitHub
(DBをデフォルトのsqliteから変更してる場合はまた別の設定が必要になると思います・・・ごめんなさい)
デプロイ環境はDjango+Nginx+Gunicornとなります。
ちなみに3分28秒というのは、
①リポジトリのクローン
②GitHub上のDjangoプロジェクトをクローン
③設定ファイル編集
④docker-compose
⑤ブラウザでの動作チェック
にかかった時間です。
概要
使い方は上記にリンクを用意しておりますGitHubのREADMEを参照ください。
簡単なデプロイを実現させるために、次のようなディレクトリ構成で動作するDjangoデプロイ用のdocker-composeを作りました。
django-nginx-gunicorn-docker/ ├ nginx/ │ └ project.conf ├ django/ │ ├ Dockerfile │ ├ requirements.txt │ └ [DJANGOPROJECT] │ ├ manage.py │ ├ … │ └ [PROJECTNAME] └ docker-compose.ymlコンテナでプロジェクトを丸ごとマウントして動作させます。
では設定ファイルをみていきます。docker-compose
利用するコンテナはDjangoアプリケーション用のもの(Gunicornもこの中で動作)と、リバースプロキシの役割を果たすNginxのコンテナです。
docker-compose.ymlversion: '3' services: django: build: ./django expose: - "8000" networks: - nginx_network volumes: - ./django:/code hostname: django-server restart: always nginx: image: nginx ports: - "80:80" networks: - nginx_network depends_on: - django volumes: - ./nginx/project.conf:/etc/nginx/conf.d/default.conf restart: always networks: nginx_network: driver: bridgedjangoのvolumesのところで、プロジェクト環境をマウントしています。もしコンテナ起動後に編集を行なっても、コンテナをrestartさせることで反映されます。
また、nginxコンテナの方では80:80でポートフォワーディングをしているので、ローカルホストの80番ポートにアクセスが来た際はnginxコンテナの方に受け渡されます。
特段トリッキーなことはしていませんので、composeの説明は終わりです。
Dockerfile
djangoディレクトリにあるDockerfileの説明です。
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/ WORKDIR /code/MYPROJECT CMD ["gunicorn", "--bind", "0.0.0.0:8000", "MYPROJECT.wsgi:application"]python3系のイメージを利用します。6行目のRUNでDjangoとGunicornをダウンロードしています。(あとついでにPostgres用のライブラリもダウンロードしていますが使っていません。ごめんなさい)
requirements.txtDjango==2.2.7 gunicorn==19.9.0 psycopg2ちなみにDjangoのバージョンですが、当初2.0を指定してGithubにあげた所くっそ怒られました。(セキュリティ警告がいっぱい来た。GitHubのBotから怒りのプルリクもきた。)
project.conf
nginxの設定ファイルです。ここで結構トリッキーな動きが必要でした。
project.confupstream django { server django:8000; } server { listen 80; server_name :localhost; location / { proxy_pass http://django; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; } }upstreamでリクエストの送信先を指定します。送信先はコンテナのlocalhostとなっています。また、ここで命名したものをプロキシパスの設定で用います。
serverのほうではlistenするポートとプロキシの設定を行なっています。
さいごに
ポートの設定でどはまりしました。。。
みなさんも気をつけましょう;;
- 投稿日:2019-11-26T19:33:53+09:00
docker-composeを使って3分28秒でDjangoをデプロイ
既に作成されたプロジェクトの場合でも対応可能な形のdocker-composeを作成しましたので、仕様を記事にまとめます。
GitHub上にHowtoUseを書いておりますのでどうぞ→GitHub
(DBをデフォルトのsqliteから変更してる場合はまた別の設定が必要になると思います・・・ごめんなさい)
デプロイ環境はDjango+Nginx+Gunicornとなります。
ちなみに3分28秒というのは、
①リポジトリのクローン
②GitHub上のDjangoプロジェクトをクローン
③設定ファイル編集
④docker-compose
⑤ブラウザでの動作チェック
にかかった時間です。
概要
使い方は上記にリンクを用意しておりますGitHubのREADMEを参照ください。
簡単なデプロイを実現させるために、次のようなディレクトリ構成で動作するDjangoデプロイ用のdocker-composeを作りました。
django-nginx-gunicorn-docker/ ├ nginx/ │ └ project.conf ├ django/ │ ├ Dockerfile │ ├ requirements.txt │ └ [DJANGOPROJECT] │ ├ manage.py │ ├ … │ └ [PROJECTNAME] └ docker-compose.ymlコンテナでプロジェクトを丸ごとマウントして動作させます。
では設定ファイルをみていきます。docker-compose
利用するコンテナはDjangoアプリケーション用のもの(Gunicornもこの中で動作)と、リバースプロキシの役割を果たすNginxのコンテナです。
docker-compose.ymlversion: '3' services: django: build: ./django expose: - "8000" networks: - nginx_network volumes: - ./django:/code hostname: django-server restart: always nginx: image: nginx ports: - "80:80" networks: - nginx_network depends_on: - django volumes: - ./nginx/project.conf:/etc/nginx/conf.d/default.conf restart: always networks: nginx_network: driver: bridgedjangoのvolumesのところで、プロジェクト環境をマウントしています。もしコンテナ起動後に編集を行なっても、コンテナをrestartさせることで反映されます。
また、nginxコンテナの方では80:80でポートフォワーディングをしているので、ローカルホストの80番ポートにアクセスが来た際はnginxコンテナの方に受け渡されます。
特段トリッキーなことはしていませんので、composeの説明は終わりです。
Dockerfile
djangoディレクトリにあるDockerfileの説明です。
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/ WORKDIR /code/MYPROJECT CMD ["gunicorn", "--bind", "0.0.0.0:8000", "MYPROJECT.wsgi:application"]python3系のイメージを利用します。6行目のRUNでDjangoとGunicornをダウンロードしています。(あとついでにPostgres用のライブラリもダウンロードしていますが使っていません。ごめんなさい)
requirements.txtDjango==2.2.7 gunicorn==19.9.0 psycopg2ちなみにDjangoのバージョンですが、当初2.0を指定してGithubにあげた所くっそ怒られました。(セキュリティ警告がいっぱい来た。GitHubのBotから怒りのプルリクもきた。)
project.conf
nginxの設定ファイルです。ここでトリッキーな動きが必要でした。
project.confupstream django { server django:8000; } server { listen 80; server_name :localhost; location / { proxy_pass http://django; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; } }upstreamでリクエストの送信先を指定します。送信先はコンテナのlocalhostとなっています。また、ここで命名したものをプロキシパスの設定で用います。
serverのほうではlistenするポートとプロキシの設定を行なっています。
さいごに
ポートの設定でどはまりしました。。。
みなさんも気をつけましょう;;
- 投稿日:2019-11-26T19:29:10+09:00
【自宅ではじめるDocker入門】アウトプット記事
Dockerとは?
Docker社が提供する、オープンソースの「コンテナ型 仮想化ソフト」
=>仮想化 : 実際にマシンを用意しなくても、仮想敵にパソコンやサーバを作れる仕組みDockerは、この仮想化をコンテナ型でおこなう
=>コンテナ : 隔離されたプログラム実行環境1つのDockerの上には、たくさんのコンテナを作成できる。
この場合でも、それぞれのコンテナは互いに影響を受けずに、独立した形で隔離された実行環境を作成できる
つまり、Dockerは、仮想敵に実行環境が作れるだけでなく、この実行環境をコンテナ単位でわけて作れる。
コンテナ
- コンテナでは、マシンとやり取りするだけの最低限の機能しか搭載されていないため、非常に軽量
- なので、1アプリ = 1コンテナで構成するのが慣例
ex)DBを使ったWebシステムの構築
- Webサーバーを担当するコンテナ
- DBを担当するコンテナの2つに分ける。リージョンを分けておく変えるみたいな?
コンテナの基
- コンテナは、イメージから作成する
- イメージは
Docker Hub
にて公開されているex)Docker Hubで公開されているイメージ
- Ubuntuがインストールされたイメージ
- Apacheがインストールされたイメージ
- MySQLがインストールされたイメージ
等々...。ここら辺をダウンロードしてしまえば、自分で設定しなくても、コマンド1つでこれらを動かせる。
カスタムしてコンテナ作成することも可能
- 起動したコンテナに対して、カスタム設定したり、追加ソフトをインストールしたりできる。
サーバー運用に最適
- Dockerではアプリのデータを保存する部分がコンテナとは別になっているので、コンテナだけ破棄して、再構築するといったmoveが簡単にできる
- アプリに異常があったら、コンテナを破棄して再構築すればOK
- バージョンアップもコンテナごと破棄して、再構築すればOK
従来のサーバー運用であれば、アプリの異常時にシステムを停止して原因解明やリカバリなどで、サーバーを元通りにして復旧していたが、Dockerは上記のような運用ができるので、ダウンタイムを最小限に抑えられる。神。
仮想マシンと仮装コンテナの違い
①仮想マシンの場合
- コンピューターそのものを仮想敵に作り出す
- つまり物理的なマシンと同じ仕組みで動くので動作が遅くなる
- さらに、OSのインストール等も必要
②コンテナの場合
- ハードウェアのエミュレートもしないし、OSも含まれていない
- コンテナに含まれているプログラムはホストOSがおこなう
※ホストOSとゲストOS
- ホストOS : 仮想マシンを動かしている物理的なマシン上のOS
- ゲストOS : それぞれの仮想マシンにインストールしたOS=>Apacheが含まれているコンテナを実行した場合、ホストOSがApacheのプログラムを隔離された場所で実行する
- 別のOSを起動しないので、OSのオーバーヘッドがなく、メモリ消費量が格段と少ない※UbuntuイメージやCentOSイメージは、OS自体が入っているのではなく、そのOSを構成するコマンドやライブラリなどのプログラム一式が入っているに過ぎない。
というわけでコンテナにOSが入っていないため、Linux上でしか使えない。
Docker利用に必要な要件
- 仮想化支援機能を搭載したCPU
- Linux環境
Linuxの環境構築方法
- 物理マシンを用意する
- 普段使っているPCに仮想マシンを用意する
- Windowsで「Docker for Windows」を使う
=>VirtualBoxで仮想マシンを準備するのが、ラクだし汎用性がありますね。
※全体像
Windows/Mac=>VirtualBox=>Linux(ubuntu)=>Docker=>コンテナ
Linux環境でDockerを使う流れ
- LinuxOSにDockerをインストールする
- Dockerで作りたいAPサーバー(=コンテナ)のベースとなるOSイメージをダウンロードする
- Dockerでダウンロードしたイメージから、コンテナを作成する
とりあえず1章はここまで。この本だとWindowsで実行していくので、Macで実行すべく別の資料なり探してみます(°_°)
- 投稿日:2019-11-26T18:43:51+09:00
docker でwordpress環境構築
忘れないように覚書。
【参考サイト】https://tech.recruit-mp.co.jp/infrastructure/post-11266/docker-composeを準備
https://docs.docker.com/compose/wordpress/
こちらの公式のdocker-composeを利用します。リポジトリを任意の名前で作成し、その中で
docker-compose.ymlを作成します。docker-compose.ymlversion: '3.3' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: db_data: {}中を上記のように編集します。
docker-compose up -dで起動します。そうすれば
http://localhost8000 でログインできます。テーマを作る
docker exec -it ドッカー名 /bin/bash上記のコマンドでdockerの中に入り、
作りたいテーマのファイルを用意。
exitでdockerから抜ける。cd /var/www/html/wp-content/themes/ mkdir mytheme exitリポジトリにもテーマ用のファイルを用意。
mkdir mythemeそしてdocker-composeの中にvolumesの記述を以下のように書き足せばOK!
これでホストマシンのテーマファイルがドッカー内のテーマファイルにマウントされます。wordpress: image: wordpress:latest ports: - "9000:80" depends_on: - db environment: WORDPRESS_DB_HOST: "db:3306" env_file: .env volumes: - ./mytheme:/var/www/html/wp-content/themes/mytheme{ホスト側の相対パス}:{コンテナ側の絶対パス} という書き方になっています。
書き換えた後に再度
docker-compose up
すれば、テーマの中を自由にいじることができるようになります!おまけ 操作上必要になるコマンド
ドッカーの停止
docker-compose stop
- 投稿日:2019-11-26T18:23:33+09:00
RailsでAPIを作ってJson形式のレスポンスを返すまで
はじめに
まとめておくと後で楽だよねってことで
環境
Ruby 2.6.5p114
Rails 6.0.1環境自体はDockerコンテナに押し込めているので、まずはDockerの設定周りからやっていきます。
Docker関連
docker-compose.yml
こちらの記事を参考にしつつ作成しています。
ENTRYPOINTは自分が理解しきれてないので指定していません。
なくても動きます。後、重要なのはmysqlのvolumesとして
/etc/mysql/conf.d
がいったん必須です。
mysql8からデフォルトの認証方式がパスワードになっていないので、それをパスワードにするために永続化して設定ファイルを入れてあげないと困ります。
認証方式変わったということは、それをデフォルトとして他を変えるのが本筋ですが、公開するサービスではないので、いったんパスワードにしています。version: '3' services: db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: password ports: - '13306:3306' volumes: - ./mysql:/var/lib/mysql - ./mysql-confd:/etc/mysql/conf.d rails: build: context: . dockerfile: ruby/Dockerfile command: bash -c "bundle exec rails s -p 3000 -b '0.0.0.0'" environment: - "DATABASE_HOST=db" - "DATABASE_PORT=13306" - "DATABASE_USER=root" - "DATABASE_PASSWORD=password" volumes: - .:/app ports: - "13000:3000"Dockerfile
こちらはRails6からwebpackerを入れる必要があるため、その設定は入れています。
今回はAPIを作るようのアプリケーションにするため、この設定はまるごといらないのですが、削除しなくても困らないので残しています。
APIモードで作らない場合はdocker-compose.ymlのcommandでインストールしてあげるかDockerfile内でインストールしてあげればOKです。あと重要なのは最後に
RUN bundle install
を入れておくぐらいでしょうか。
Gemを書き換えた際にはイメージを書き換えないと駄目っぽいのですが(本当か?)、これやっておかないと起動時にGemがないと言われて怒られます。
1個目の方はRails関連のGemを入れるようなので、別にやっておかないとアプリケーションの方のGemの読み直してくれません。※
ここも色々参考にさせていただいた記事があるのですが、見つけ次第追記します。
どの記事だっけなぁ・・・FROM ruby:2.6.5 ENV TZ='Asia/Tokyo' RUN /bin/cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ENV LANG C.UTF-8 RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update -qq && apt-get install -y nodejs yarn RUN gem install bundler WORKDIR /tmp ADD ruby/Gemfile Gemfile ADD ruby/Gemfile.lock Gemfile.lock RUN bundle install ENV APP_HOME /app RUN mkdir -p $APP_HOME WORKDIR $APP_HOME ADD . $APP_HOME RUN bundle installGemfile
バージョンは適宜読み替えてください。
Gemfile.lockは参考にある通り空ファイルです。Gemfileはrailsアプリケーションを生成した際に上書きされると困るので、rootフォルダとは別の場所に置いてあります。
source 'https://rubygems.org' gem 'rails', '~> 6.0.1'railsアプリケーションの生成
ファイルの準備が出来たらアプリケーションを生成します。
docker-compose run rails rails new . --api --force --no-deps --database=mysqlconfig/database.yml
立ち上げる前にデータベースの設定を書き換えます。
passwordとhostの書き換えだけです。docker-composeでアプリケーションを作成するとネットワークをいい感じで作ってくれるため、hostをサービス名で設定しておけばいいので楽ですね。
docker-composeで設定したportsもこのネットワーク外部から繋いだ時のものでネットワーク内部からは普通のportで接続となります。default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password host: dbdatabase作成
rakeコマンド使うなり自力で作るなりしてDB作っておいてください。
docker起動
ビルドして起動します。
中々に時間がかかるので、間違えてやり直しをするのが結構辛かったです。docker-compose build docker-compose up -d起動確認
localhost:13000
につないで画面出ればオッケーです。
駄目ならエラー見つつ頑張ってください。routes.rbの設定
起動したので、routesを書いてURLを生成します。
適当でも良いですが、せっかくなので少し真面目に書きます。
resourcesをnewsにしているのは作ろうとしているアプリケーションのURLだからです。routes.rbRails.application.routes.draw do namespace :api do namespace :v1 do resources :news end end endrouteの確認
railsの操作をする際は色んなことをやっていくことになるので、内部で操作していった方が楽だと思います。外からでも操作できるので、どっちでも良いです。
入ってやる方は以下のコマンドで入れます。docker-compose exec rails bash確認したらこんな感じで出ると思います。
rails初期から存在するrouteと共に設定したrouteが見れます。これで上のrouteが正しく設定されたことを確認します。
root@69c223a51ae2:/app# rails routes Prefix Verb URI Pattern Controller#Action api_v1_news_index GET /api/v1/news(.:format) api/v1/news#index POST /api/v1/news(.:format) api/v1/news#create api_v1_news GET /api/v1/news/:id(.:format) api/v1/news#show PATCH /api/v1/news/:id(.:format) api/v1/news#update PUT /api/v1/news/:id(.:format) api/v1/news#update DELETE /api/v1/news/:id(.:format) api/v1/news#destroy rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create rails_conductor_inbound_emails GET /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#index POST /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#create rails_conductor_inbound_email GET /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#show PATCH /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update PUT /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#update DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#destroy rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#createcontrollerの作成
これもコマンドで作成します。
Controllerの名前はroutesで確認したControllerと同じにする必要があるので、その点だけ注意ください。rails generate controller api/v1/news作ったら中身です。
news_controller.rbclass Api::V1::NewsController < ApplicationController def index render json: { status: 'SUCCESS'} end endとりあえずのレスポンスを返却するためだけの中身です。
途中でキャッシュ関連で変更が反映されないという問題に直面しましたが、その際はこちらを参考にして解決しました。
Rails6でも同様の方法で解決できるようです。終わりに
Rails使うならここまではぱぱっと出来るようになりたいですね。
一通りやってみて環境構築周りの注意点とか分かったので、やっぱり手を動かして作るって大事です。
- 投稿日:2019-11-26T15:36:53+09:00
MacでDocker上に日本語環境のPostgreSQLを建てる
前書き
- Docker に PostgreSQL コンテナを日本語環境でサクッと建てたい!
- PostgreSQL のバージョンは最新のバージョンにしたい!
- Mac で作業したい!
- AWS RDS の PostgreSQL とバージョンを合わせた PostgreSQL コンテナを建てたい!
を叶えるためのメモ。
MacでDocker上に日本語環境のMySQL8.0を建てる の PostgreSQL 版です。
タイトルで Mac と謳っていますが上記の MySQL 版と同様に Windows でもほぼ同じ手順です。
違いは Docker のインストーラーが Mac 用か Windows 用かだけです。
なお、このページの文体・構成は上記 MySQL 版 に合わせています。環境
- Mac 10.15.1 (Catalina)
- Docker for Mac
事前準備
Docker Desktop for Mac をインストールする
参考URL:https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81Kitematic をインストールする
→DockerコンテナをGUIで操作できるアプリ。インストール手順はタスクトレイのDockerアイコンから。
docker-composeで設定した共有ディレクトリやポートなどの確認もこれで行いました。docker-composeでPostgreSQLコンテナを立てる
参考URL
上記を参考に、PostgreSQLのコンテナを日本語環境で建てる。
特に1つ目のリンクはほぼそのまま参考にさせていただきました。とても詳しく記載されているので、当記事よりは1つ目のリンクを参考にしたほうが良いと思います。docker-compose.ymlversion: '3' volumes: # ※ホストOSで永続化 postgres_data: driver: 'local' services: postgres: build: context: ./postgres dockerfile: Dockerfile container_name: "postgres_db" environment: POSTGRES_PASSWORD: postgres #スーパーユーザ(postgres)のパスワード POSTGRES_USER: test #ユーザアカウント POSTGRES_PASSWORD: password #ユーザアカウントのパスワード POSTGRES_DB: testDb #DB名 TZ: "Asia/Tokyo" ports: - 15432:5432 volumes: - postgres_data:/var/lib/postgresql/data # ※ホストOSで永続化 - ./postgres/sql:/docker-entrypoint-initdb.dDockerfileFROM postgres:12.1 RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 ENV LANG ja_JP.utf8上記のディレクトリイメージは以下の通り。
├── docker-compose.yml └── postgres ├── Dockerfile (上記のファイル) └── sql (ディレクトリ)接続確認は適当なDBクライアントでOK。 当方は
DBeaver
で確認しました。初期構築用のCreateTableやInsertなどのSQLファイルはsqlディレクトリに放り込むイメージです。
PostgreSQLのファイルをホストOS側で永続化する必要がない(コンテナ内で保持する)場合は、docker-compose.xml の
※ホストOSで永続化
とコメントしている部分の設定を削除してください。メモ
日本語を使用するための設定が MySQL 版 で記載したものと違うけど?
そもそもMySQLとPostgreSQLの各Docker Hub の Official ページで公開されているコンテナのDockerfile内のロケール・言語の設定が異なるため。
MySQL 版の Dockerfile では元になっているDebianのロケール・言語設定をそのまま使用すようになっているため、ロケール・言語として日本語を使用するための設定が必要になります。
反面 PostgreSQL 版 のDockerfile ではUTF-8を使用する設定がされているため、ロケールだけ変更すればOKとなっています。AWS RDS for PostgreSQL とバージョンを揃えたい
Amazon RDS for PostgreSQL のよくある質問 を見ると、AWS RDS for PostgreSQL で使用されているバージョンは、
PostgreSQL 9.4、9.5、9.6、10、および 11
となっています。(当ページ記載時点)
そのため、上記バージョンを使用するにはDockerfile
の FROMタグ部分を以下のいずれかにすればOK
※ここでは簡素に記載しています。正確な情報・詳細は PostgreSQL の Docker Hub Officialページ を参照してください。
- FROM postgres:9.4
- FROM postgres:9.5
- FROM postgres:9.6
- FROM postgres:10
- FROM postgres:11
Postgresコンテナの永続化用のボリュームを削除したい
Docker volumeの削除 を参考に、
当ページ内のコンテナの場合は以下で削除できます。docker volume rm postgresql_postgres_data
ボリュームの一覧を確認する場合は以下のコマンドです。
docker volume ls
- 投稿日:2019-11-26T14:16:56+09:00
Docker環境構築するときに(きっと)便利なコマンドたち
この2日ほど、Dockerで色々試行錯誤してたときに便利だったコマンドたちです。
<none>でできたイメージを一括削除
何も考えずに作っているとVMの容量が100%になっちゃうときがあります(ありました)。
docker image prune
でキレイにできます。こちらはimages
ではなくimage
のようです。$ docker image prune WARNING! This will remove all dangling images. Are you sure you want to continue? [y/N] y Deleted Images: deleted: sha256:18abcdefghijklmnopqrstuvwxyz19abcdefghijklmnopqrstuvwxyz20abcdef deleted: sha256:21abcdefghijklmnopqrstuvwxyz22abcdefghijklmnopqrstuvwxyz23abcdef . . . Total reclaimed space: 5.344GB最後に空いた容量をドヤ顔で教えてくれます。
--rmオプションで終了時にコンテナ削除
基本ですが一応……
--rm
オプションをつけると、コンテナを終了させたときにコンテナ自体も削除してくれます。
検証してるときは何度も同じコンテナ名で起動/終了をさせると思うので必須です。
ちなみに-d
オプション(バックグラウンド起動)のときにも有効です。昔はできなかった気がするなぁと思って調べたらどっかのバージョンからできるようになったんですね。commandline$ docker run --rm -it jupyter/notebook:latest bashENTRYPOINTを無効にして起動
DockerfileにENTRYPOINTを指定して、
docker run
時に何かしらを一緒に起動することができますが、環境構築時はシェルを起動していろいろと検証を行いたいときがあるとおもいます。いちいちDockerfileをいじらなくても、起動時に無効にすることが可能です。commandline$ docker run --entrypoint '' --rm -it jupyter/notebook:latest bash
--entrypoint ''
と明示的に空にすることで無効にできるようです。起動しているコンテナからイメージ作成
あるコンテナで作業したのをイメージとして残しときたい、とか思ったときに便利なのがcommitです。
$ docker commit 33aabcdefg33 test-docker-commit-image sha256:24abcdefghijklmnopqrstuvwxyz25abcdefghijklmnopqrstuvwxyz26abcdef $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE test-docker-commit-image latest f2abcdefg1f 7 seconds ago 4.81GB
docker commit <コンテナID> <作成するイメージ名>
で指定します。
当然ですが、Dockerfileから作っているわけではないので再現性がありません。イメージからDockerfile作成
そんな感じでコンテナから残したイメージをDockerfile化したい、といったとき。
そのものずばりなコマンドはないのですが、historyである程度どういう作業をしたかが把握できます。ここからDockerfileに反映していくといいかなと思います。$ docker history test-docker-commit-image:latest IMAGE CREATED CREATED BY SIZE COMMENT af14d0dd9f68 About a minute ago 19.9MB b4abcdefgh51 6 hours ago /bin/sh -c #(nop) ENTRYPOINT ["/bin/sh" "... 0B 70abcdefgh99 6 hours ago /bin/sh -c #(nop) EXPOSE 8888/tcp 0B 26abcdefghe5 6 hours ago /bin/sh -c #(nop) WORKDIR /notebook 0B a6abcdefghaa 6 hours ago /bin/sh -c #(nop) VOLUME [/notebook] 0B
--no-trunc
オプションをつけるとCREATED BY
の部分が省略されずに表示されます。
ただ……試した環境が悪かったのか、手動でapt-get update
やapt-get install
したのが表示されずあれ?となってます。ちょっと検証が必要ですがこういうコマンドもあるんだということで。昔、太古のバイナリファイルしかない環境で、gdbとかnmとかobjdumpを駆使して泣きそうになりながらソースに反映したのを思い出しました……。
参考文献
https://qiita.com/DQNEO/items/e3a03a14beb616630032
https://qiita.com/nju33/items/733e16511f3b8e739d54
- 投稿日:2019-11-26T13:50:59+09:00
【Docker】GitHubと連携してDockerイメージを自動ビルドする手順
はじめに
GitHubに
push
したらDockerイメージが自動ビルドできる
Automated Builds
を設定したときの手順を備忘録としてまとめました。【背景】
先日愛用のMacBookが壊れてしまったのですが、一時的に別端末に開発環境を構築するハメになったのですが、Dockerも使っていなかったので「かなり面倒」でした。そのため、Dockerfileにも保険をかけておこうと思い導入したのが経緯です。
以下参照した公式サイトです。
Set up automated builds | Docker Documentationこの記事が役に立つ方
- DockerとGitHubを使用していて、自動ビルドは導入していない方
この記事のメリット
- 常に最新のDockerイメージがDockerHubにある状態を維持出来る。
環境
- macOS Catalina 10.15.1
- zsh: 5.7.1
- Docker: 19.03.5
前提
今回は開発途中からDockerイメージの自動ビルドを行います。
以下2つのアカウントは取得済とします。
- GitHub
- DockerHub
スムーズに設定するためにそれぞれ事前にログインしておきましょう。
1.アカウントの連携
Docker Hubにアクセス。
↓
ログイン後、アカウント名をクリックし、Account Settingsをクリック。
↓
左側メニューの中からLinked Accountsをクリック。
↓
GitHub側のConnectをクリック。
※他にBitbucketも連携可能です。ログインしていれば出てきた画面でAuthorize dockerをクリックして連携完了。
2.リポジトリの連携
次はリポジトリ同士の連携です。
まずはDockerHubのリポジトリを作成します。
①上部メニューのRepositoriesをクリック
②Create Repositoryをクリック↓
リポジトリ名とDockerイメージの詳細説明を任意で設定し、GitHubアイコンをクリック。
↓
どのリポジトリと連携するかをプルダウンメニューから選ぶ。
必要があればどのBranchを対象として自動ビルドするかも設定する。(デフォルトはmaster)
↓
リポジトリ同士の連携完了。確認
DockerHubのヘッダーメニューにあるRepositories
↓
作成したリポジトリ名をクリック
↓
Buildsタブをクリック
↓
Automated Buildsにビルドの状況が表示されています。その他、Recent Buildsからビルドされた時点それぞれのログ、Dockerfile、READMEがブラウザ上で確認出来るようになっています。便利。
おわりに
最後まで読んで頂きありがとうございました
最新のDockerイメージがDockerHubに上がっていれば、端末が壊れたり別端末から作業をするときにも開発環境をすぐ戻せるので安心ですね
参考にさせて頂いたサイト(いつもありがとうございます)
- 投稿日:2019-11-26T13:29:27+09:00
CentOS8でdocker buildのdnf installが失敗する
CentOS8でdocker buildのdnf installが失敗する
社内VPNでNginxを立てようとしたときの話。
CentOS8とDockerをインストールし、docker buildを行ったところdnf installが上手くいかずハマったのでメモ。環境
- CentOS Linux release 8.0.1905 (Core)
Docker version 18.06.3-ce, build d7080c1
SELinux
# getenforce Enforcing
- Firewalld
# firewall-cmd --list-all public (active) target: ACCEPT icmp-block-inversion: no interfaces: enp1s0 sources: 192.168.0.0/16 services: cockpit dhcpv6-client http https ssh ports: 8000/tcp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:Dockerのサービス変更
# vi /usr/lib/systemd/system/docker.serviceDockerサービスにて生成されるファイルパスの変更とDNS指定を行いました
Environment="DOCKER_OPTS=-g /mnt/HDD/docker/system --dns=8.8.8.8" ExecStart=/usr/bin/dockerd $DOCKER_OPTSDockerサービスを再起動
# systemctl daemon-reload # systemctl restart dockerDockerfile
# cat Dockerfile FROM centos:8 MAINTAINER name <email> EXPOSE 80 RUN dnf install -y nginx CMD ["nginx", "-g", "daemon off;"]ビルドしてみた
# docker build -t nginx -f Dockerfile .dnf installで失敗する。
AppStreamやBase、Extrasに0MBと表示され、dnf install nginxが失敗しました対策
Dockerfileにpingを書いてみたところ、IPアドレス指定であれば反応があるが、URL指定だと失敗しました。
よって、DNSによる名前解決ができず、dnf installが失敗しているようです。
docker buildで下記のようにホストのネットワークを指定したところ問題なくビルドできました。# docker build -t nginx -f Dockerfile --network host .
- 投稿日:2019-11-26T10:00:44+09:00
ローカルで作ったDockerコンテナをCloud Run で公開するまで
Google Cloud Platform Advent Calendar 2019の6日めです。
こちらの記事で作成したDockerコンテナをCloudRunにアップしたい!というわけでやってみました。
必要なもの
- Google Cloud SDKの最新バージョンのインストール
- 課金が有効になっているGCPプロジェクト
- アプリの入ったDockerコンテナ(Dockerはインストールされている前提:sudoなしで実行できるように) (ベータ版の間は「HTTP」しか対応していないとの噂あり)
環境
- MacOS Mojave 10.14.6
- Docker 19.03.4
- Google Cloud SDK 270.0.0
準備
準備として必要なのは以下です。
- デプロイ対象のGCPプロジェクトの確認
- Croud Run の有効化
- 認証ヘルパーの設定
- ローカルイメージの編集
デプロイ対象GCPプロジェクトの確認
UP先のプロジェクトが正しいか、gcloudの設定を確認しておきます。
間違えて違うプロジェクトにUPしちゃうと、えらいことになりますので
設定を確認するだけならgcloud config list
で表示できますが、
もし編集が必要な場合はgcloud config set ~
コマンドを使って設定してください。
(もしくはgcloud init
?ちょっと調べてくださいー)$ gcloud config list [compute] region = asia-northeast2 zone = asia-northeast2-b [core] account = sample@test.com(アカウントのメールアドレス) disable_usage_reporting = False project = sandbox-a(プロジェクト名)CroudRunの有効化
GCPのメニューから、「コンピューティング」 > 「Cloud Run」を
選択すると、こんな画面になります。
「CLOUD RUN の使用を開始する」 をクリックします。認証ヘルパーの設定
次のコマンドを実行して、gcloudを認証ヘルパーとして使用します。
認証方法としては他にも存在するようですが、どれもめんどくさそう高度なので保留にします。
気になる方はこちらをどうぞ。$ gcloud auth configure-dockerローカルイメージの編集
UPしようとしていたdockerイメージはこちらの記事にて作成したものです。
開発用にホットリロードつけるため、「docker-compose」を使用しています。
ところがどっこい。CloudRunではdocker-composeは使えないそうです。
(知らなかった。。。)確かによく考えたら、ホットリロードの設定だったり、
複数コンテナを同時に起動させるだったり、
役割としてはローカル用と言われればその通りかも。
公開したらファイル更新ではなくて、イメージごと更新ですものね。。。
危ない危ない。またモノシリックの罠にハマるところでしたよ。。。というわけで、Dockerfileを修正します。
Dockerfile
- ホットリロード用のライブラリの読み込み削除
- 実行コマンド追加(開発用ではdocker-compose.ymlに記載していた)
# 公式 golang ランタイムを親イメージとして使用 FROM golang:1.13 RUN mkdir -p /attendance/app WORKDIR /attendance/app COPY ./app /attendance/app RUN go get -u github.com/labstack/echo/... RUN go get golang.org/x/oauth2 #ホットリロード用なのでコメントアウト #RUN go get github.com/oxequa/realize #実行コマンド追加 CMD ["go", "run", "/attendance/app/server.go"]server.go
CloudRunのドキュメントには以下の通り書かれてます。
平たい話が、起動するポートは「PORT」っていう名前の環境変数から取得してね、
ってことでしょうか。
番外編でやるんですけど、GUIでのデプロイ時にコンテナポートを設定する項目があります。
ここの項目を使うためなのでしょうね。それもあって、ソース内へのハードコーディングはして欲しくないようです。
Listening for requests on PORT
The container must listen for requests on 0.0.0.0 on the port defined by the PORT environment variable.
In Cloud Run container instances, the PORT environment variable is always set to 8080, but for portability reasons, your code should not hardcode this value.
(PORTでリクエストをリッスンする
コンテナは、PORT環境変数で定義されたポートで0.0.0.0でリクエストをリッスンする必要があります。
Cloud Runコンテナインスタンスでは、PORT環境変数は常に8080に設定されますが、移植性の理由から、
コードでこの値をハードコーディングしないでください。)https://cloud.google.com/run/docs/reference/container-contract?hl=ja
というわけで、以下の内容を追加しました。
server.goimport "os" //追加 func main() { e := echo.New() routing(e) // ルーティング // 追加 ここから --------------------- port := os.Getenv("PORT") if port == "" { port = "8080" } // 追加 ここまで --------------------- e.Logger.Fatal(e.Start(":" + port)) //[port]部分を変数に修正 }タグつけ & Container Registry へのPUSH
上記の通り修正した者たちに、次のコマンドを実行して、pushしたいイメージに
タグ付け(命名?!)を行います。$ gcloud builds submit --tag [ホスト名]/[GCPプロジェクト名]/[GCP内でのイメージ名]:[タグ]ex)
gcloud builds submit --tag asia.gcr.io/sandbox-a/hello:v1
[ホスト名]
イメージのUP先のリージョンを設定します。
居住地にかかわらず、以下の4つの中からどこでも好きなところを指定できます。
- gcr.io :米国(今後、場所が変更になる可能性あり)
- us.gcr.io :米国(ただし、gcr.ioからは独立したストレージバケット)
- eu.gcr.io :欧州連合
- asia.gcr.io :アジア
[GCPプロジェクト名]
先に確認したプロジェクトIDを設定します。
※たまに、プロジェクト名とプロジェクトIDが異なる場合があるそうですが、
あくまで「プロジェクトID」を指定してください。
プロジェクトIDに「:(コロン)」が含まれる場合はこちらを参照してください。[GCP内でのイメージ名]:[タグ]
ローカルマシン上のイメージ名とは異なるイメージ名を設定する必要があるようです。
タグは省略可能ですが、その場合、デフォルトで「latest」が設定されます。
バージョン管理をちゃんと行う意味でも、タグは設定しておいた方がいいかも。完了すると、こんな感じで表示されます。
ID CREATE_TIME DURATION SOURCE IMAGES STATUS exxxxxxx-fxxx-4xxx-8xxx-46xxxxxxxxxx 2019-12-02T06:36:51+00:00 1M12S gs://sandbox-axxxxxx_cloudbuild/source/15xxxxxxxx.65-abac751c9418xxxxxxxxxxxxxxxxxxxx.tgz asia.gcr.io/sandbox-axxxxxx/hello:v1 SUCCESSGCP > [ツール] > [Container Registry]でも確認できます。
(似たような名前がいっぱいあるのは試行錯誤の末消せなくなったのです・・・)
※ここで設定した「asia.gcr.io〜」のタグはあとで使います。
deploy
いよいよ、デプロイです。
こちらは、GCPの Croud Shell にて実行します。(ここをポチってするやつ)
以下のコマンドを実行します。
対話型で設定していきます。$ gcloud run deploy --image [さっき設定したタグ] --platform managed ex)gcloud run deploy --image asia.gcr.io/sandbox-a/hello:v1 --platform managed Please specify a region: [1] asia-northeast1 [2] europe-west1 [3] us-central1 [4] us-east1 [5] cancel Please enter your numeric choice: 1 <-- ここでリージョンを選択 To make this the default region, run `gcloud config set run/region asia-northeast1`. Service name (hello): --> サービス名。空白にすると、デフォルトの「hello」が採用される。上書きしたければ記載してEnter Allow unauthenticated invocations to [hello] (y/N)? y --> [y]を選択すると、認証無しになる。アクセス認証を設定したい場合は[N]にする。 Deploying container to Cloud Run service [hello] in project [sandbox-akiando] region [asia-northeast1] ✓ Deploying new service... Done. ✓ Creating Revision... Revision deployment finished. Waiting for health check to begin. ✓ Routing traffic... ✓ Setting IAM Policy... Done. Service [hello] revision [hello-00001-yiv] has been deployed and is serving 100 percent of traffic at https://hello-vlxxxxxxxx-xx.x.run.app最後に表示されている
https://hello-vlxxxxxxxx-xx.x.run.app
の部分がURL。というわけで、ブラウザでやってみる。
よしきた!
これで、デプロイまではできました。はー、長かった!!
まとめ
とりあえず、作ったDockerコンテナをGCPのサービスに公開することはできました。
GKEでやるつもりだったんだけど、CloudRunを触ってみたくて。。。
GKE版を試してみて、違いを見てみるのも楽しいかもですねー。あとは認証情報の設定が残っているな。。。
(むしろデプロイの仕方よりも、性能比較の方がいい?
・・・それはどなたかにお任せしますw)番外編その1: GUIでのデプロイ
GUIでもdeployはできます。
(Container Registryへの登録まではCUIですが)
あまり推奨はされてないという噂を聞きましたが、一応、公式のドキュメントにも
載っていたので記載してみます。[コンピューティング] > [Cloud Run]を選択して、「サービスを作成」をクリック。
使用イメージは「選択」をクリックすると、リストが表示されます。
さっきpushしたイメージが表示されてますね。なんて便利。
で、こんな感じで入力します。
コンテナはさっき選択できたし、サービス名はわかりやすく変更しておきます。
それから「オプションのリビジョン設定を表示」リンクをクリックします。
基本的にデフォルトから変更することはないと思うんだけど、ビビりなので
MAXインスタンス数だけ、デフォルトの1000から10に変えときました。
(もっと少なくてもいいけど。お金は大事)合わせてハマりどころだったのが、ポートは今の所8080にしておいたほうがいいのかも。
ちょっとここは変更するとうまくいかなかったので今後検証します。
(噂ではベータ版は8080のみ対応だったみたい。)
入力できたら「作成」ボタンをクリックします。
ちょっと待ちますが、こんな感じで緑のチェックがついたらOKかと。やったね!
番外編その2: docker-credential-gcr
もしかしたらいらないかもだけど。
上記の手順でうまくいかなかったら、これも試してみてください。
(いろいろ試行錯誤しながらだったので、もしかしたらいるのかも。多分関係ないと思うんだけどなー)$ gcloud components install docker-credential-gcr $ docker-credential-gcr gcr-login参考
https://cloud.google.com/container-registry/docs/pushing-and-pulling?hl=ja
https://toranoana-lab.hatenablog.com/entry/2018/10/22/123848Special Thanks!!
となりの堤さん
- 投稿日:2019-11-26T04:49:19+09:00
no space left on deviceエラーの対応
> docker exec front df -i Filesystem Inodes IUsed IFree IUse% Mounted on overlay 3907584 3907459 125 100% / # skip osxfs 9223372036854775807 3103606 9223372036851672201 1% /root/dev /dev/sda1 3907584 3907459 125 100% /etc/hosts # skipTL;DR;
macで
docker-compose up
したらINODES枯渇で落ちてしまう問題に効果のあったのはvolume削除
- コンテナ削除も少し効果あり
- イメージ削除もごく僅かに効果あり
今回の
no space left on device
の原因
docker-compose up
時に遭遇- 原因がディスク容量不足ではない
- 仮に容量不足なら
docker.app
の設定を変更するだけなので話が早い- コンテナの中にINODESを食い尽くしているファイルは特に無い
- フレッシュなオフィシャルイメージでコンテナ作った段階でのINODES100%
- そもそも削れるファイルが無いケース
volume削除
一番効果あった。自分の場合は30%以上減らせた
# activeでないvolumesを確認する docker system df # dangling volumeのリストを確認 docker volume ls -q -f dangling=true # 参照されてないvolumesを削除 docker volume rm `docker volume ls -q -f dangling=true`コンテナ削除
若干効果あった。自分の場合は利用率を10%弱減らせた
docker rm xxxx使ってないコンテナxxxxx
イメージ削除
わずかに効果あり。1-2%削減
docker system df
でactiveでないイメージが相当ある場合は試してもよいかもしれない# danglingイメージや、<none> 表示になってるイメージを削除 docker rm xxxx使ってないコンテナxxxxx