- 投稿日:2019-10-12T23:51:34+09:00
Dockerでよく使うコマンド集
はじめに
この記事はコンテナ勉強用として試したことまとめたものです。
(ほぼ自分が使用するもの...随時追加予定)Dockerコマンド
- イメージのダウンロードコマンド
docker image pull [オプション] イメージ名 [:タグ名]# docker image pull centos:7 7: Pulling from library/centos 8ba884070f61: Pull complete Digest: sha256:a799dd8a2ded4a83484bbae769d97655392b3f86533ceb7dd96bbac929809f3c Status: Downloaded newer image for centos:7 docker.io/library/centos:7 #
- イメージの一覧表示コマンド
docker image ls [オプション] [リポジトリ名]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 5a3221f0137b 41 hours ago 126MB centos 7 9f38484d220f 5 months ago 202MB hello-world latest fce289e99eb9 7 months ago 1.84kB #
- イメージの詳細情報
docker image inspect [イメージ名]# docker image inspect centos:7 [ { "Id": "sha256:9f38484d220fa527b1fb19747638497179500a1bed8bf0498eb788229229e6e1", "RepoTags": [ "centos:7" ], "RepoDigests": [ "centos@sha256:a799dd8a2ded4a83484bbae769d97655392b3f86533ceb7dd96bbac929809f3c" ], "Parent": "", "Comment": "", "Created": "2019-03-14T21:19:53.361167852Z", "Container": "958baf5225f586da9c70a21e911a0a875402dd22d83133d78b3b3aa6130e7892", "ContainerConfig": { "Hostname": "958baf5225f5", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/bash\"]" ], "ArgsEscaped": true, "Image": "sha256:294e8d8145287e70f07328cc09d840fad8980b801223321b983442f097aff0d8", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20190305", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS" } }, "DockerVersion": "18.06.1-ce", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "ArgsEscaped": true, "Image": "sha256:294e8d8145287e70f07328cc09d840fad8980b801223321b983442f097aff0d8", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20190305", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS" } }, "Architecture": "amd64", "Os": "linux", "Size": 201775492, "VirtualSize": 201775492, "GraphDriver": { "Data": { "DeviceId": "10", "DeviceName": "docker-253:0-50575843-a8cd5245187bae41a0457a7100bac56e3468e9a74d4eeab24091a5b772a899ae", "DeviceSize": "10737418240" }, "Name": "devicemapper" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ] #
- Dockerfileからイメージを作成
docker build -t [作成するイメージ名]:[タグ名] [Dockerfileの場所]# docker build -t test-docker:latest ./ Sending build context to Docker daemon 3.584kB Step 1/4 : FROM centos:centos7 ---> 67fa590cfc1c Step 2/4 : RUN ["yum", "-y", "install", "httpd"] ---> Using cache ---> 37f12e15f83e Step 3/4 : COPY index.html /var/www/html ---> Using cache ---> fbafd7674218 Step 4/4 : CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"] ---> Using cache ---> d59edf5b5938 Successfully built d59edf5b5938 Successfully tagged test-docker:latest #
- Dockerコンテナ起動
docker run [オプション] [イメージ名:タグ名] [引数]# docker run -it test-ubuntu-docker root@0e0479ff474v:/#
- イメージの削除
docker rmi [オプション] [イメージID]# docker rmi -f golang Untagged: golang:latest Untagged: golang@sha256:1b1246987ecb4939d9bd20f74eab25e8e2ad819aceea2d6b59869c82f85ef1de Deleted: sha256:52b59e9ead8e18fafb497532ed44ee8ee4833082b9874abbf0bca61a713a4e01 Deleted: sha256:037466601c73650bce9e801284525d2cb01076d83152e3f52b58a4f1db93cd92 Deleted: sha256:bfe10948239b9bb3c686f973f558bf3b13e5a4e5836a6e2ca10160ce3cec52f0 Deleted: sha256:1daff011bfed534d3a97f224a10f0345bb856f3ee68c885515f0840875ff1502 Deleted: sha256:aeed80cc2bd89729d4743c112894e46bf3e454e23035fca42d8c2317d76e6b59 Deleted: sha256:4d46c2665dc95257b2142eff58b4ca0e01c39238ce5722c573b351a86f6db59d Deleted: sha256:5bfb8954c951a40ba691ad40d8c6403564ab3ec406bb33693c15a145a4e6cede Deleted: sha256:78c1b9419976227e05be9d243b7fa583bea44a5258e52018b2af4cdfe23d148d #
- 投稿日:2019-10-12T21:22:16+09:00
Docker 環境構築(php+nginx+mysql+memcached)
ディレクトリ構成
---docker |--docker-compose.yml |--docker | |--nginx | | |--Dockerfile | | |--nginx.conf | | |--conf.d | | |--default.conf | | | |--phpfpm | | |--Dockerfile | | |--php.ini | | | |--mysql | | |--Dockerfile | | |--my.cnf | | | |--memcached | |--Dockerfile | |--volumes |--db | |--data | |--logs |--nginx |--www |--html |--webcoredocker-compose.ym
FROM php:7.3-fpm-alpine RUN apk update \ && apk add \ autoconf \ vim \ git \ zip \ gcc \ g++ \ make \ libmemcached-dev \ zlib-dev \ freetype-dev \ libjpeg-turbo-dev \ libpng-dev \ libmcrypt-dev \ postgresql-dev \ && pecl install memcached \ && docker-php-ext-install \ mbstring \ json \ exif \ mysqli \ pdo_mysql \ gd \ pgsql \ pdo_pgsql \ hashnginx
:latestと:alpineの違い
:latest → bash/shが使用可能
:alpine → shのみ使用可能Dockerfile
FROM nginx:alpineconf.d/default.conf
mysql
Dockerfile
#イメージ指定 FROM mysql:5.7my.cnf
[mysql] default-character-set=utf8mb4 [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci explicit_defaults_for_timestamp=1 default-time-zone=Asia/Tokyo max_allowed_packet=32M skip-symbolic-links=1 [client] default-character-set=utf8mb4phpfpm
Dockerfile
FROM php:7.3-fpm-alpine RUN apk update \ && apk add \ autoconf \ vim \ git \ zip \ gcc \ g++ \ make \ libmemcached-dev \ zlib-dev \ freetype-dev \ libjpeg-turbo-dev \ libpng-dev \ libmcrypt-dev \ postgresql-dev \ && pecl install memcached \ && docker-php-ext-install \ mbstring \ json \ exif \ mysqli \ pdo_mysql \ gd \ pgsql \ pdo_pgsql \ hashphp.ini
[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese" [extension] enabled_dl = On [memcached] extension=memcached.sophp-fpm.conf
memcached
Dockerfile
FROM memcached:latest
- 投稿日:2019-10-12T21:22:16+09:00
Docker 環境構築(php+nginx+mysql)
ディレクトリ構成
---docker |--docker-compose.yml |--docker | |--nginx | | |--nginx.conf | | | |--phpfpm | | |--Dockerfile | | |--php.ini | | | |--mysql | |--Dockerfile | |--my.cnf | |--volumes |--db | |--data | |--logs |--nginx |--www |--html |--webcoremysql
Dockerfile
#イメージ指定 FROM mysql:5.7my.cnf
[mysql] default-character-set=utf8mb4 [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci explicit_defaults_for_timestamp=1 default-time-zone=Asia/Tokyo max_allowed_packet=32M skip-symbolic-links=1 [client] default-character-set=utf8mb4phpfpm
nginx
:latestと:alpineの違い
:latest → bash/shが使用可能
:alpine → shのみ使用可能
- 投稿日:2019-10-12T20:13:41+09:00
Docker 削除まとめ
コンテナとイメージの削除
それぞれを削除する必要あり
コマンド実行時は前方一致で削除されるため要注意コンテナ削除
docker rm CONTAINER_IDコンテナ削除(停止中のみ)
for /f "usebackq" %x in (`docker ps -aq`) do docker rm %xコンテナ削除(すべて)
for /f "usebackq" %x in (`docker ps -aq`) do docker rm -f %xイメージ削除
docker rmi IMAGE_IDイメージ削除(すべて)
for /f %T IN ('docker images --format "{{.ID}}"') DO docker rmi %T
- 投稿日:2019-10-12T20:13:41+09:00
Docker コマンドまとめ
バージョン確認
docker version実行環境確認
docker infoイメージ操作
ダウンロード
オプションは
-a すべてのタグdocker pull IMAGE_NAME:[TAG_NAME] [OPTION]一覧表示
docker images []検索
-stars=%d スターの数
docker search [KEYWORD]コンテナとイメージの削除
それぞれを削除する必要あり コンテナ→イメージ
コマンド実行時は前方一致で削除されるため要注意docker system prune docker container prune docker image prune docker volume prune docker network pruneコンテナ削除
docker rm CONTAINER_IDコンテナ削除(停止中のみ)
for /f "usebackq" %x in (`docker ps -aq`) do docker rm %xコンテナ削除(すべて)
for /f "usebackq" %x in (`docker ps -aq`) do docker rm -f %x docker rm `docker ps -a -q`イメージ削除
-f 強制オプション
docker rmi IMAGE_IDイメージ削除(すべて)
for /f %T IN ('docker images --format "{{.ID}}"') DO docker rmi %Tコンテナ生成
起動
-d バックグラウンド
-e 環境変数設定
--env-file 環境変数一括設定docker run [OPTION] IMAGE_NAME[:TAG_NAME] docker run -e ENV=dev IMAGE_NAME docker run --env-file=ENV_FILE.txtコンテナ 一覧表示
-a すべて
-f フィルタリングdocker ps [OPTION] docker ps -a docker ps -f 'NAME=VAL'コンテナ ステータス確認
docker status CONTAINER_ID docker status KEY1[ KEY2 KEY3]コンテナ詳細確認
docker inspect CONTAINER_IDコンテナ ビルド
--no-cache
docker buildコンテナ 起動
docker start CONTAINER_ID [OPTION] docker restart CONTAINER_ID [OPTION]コンテナ 停止
-t NUM NUM秒後に停止
docker stop CONTAINER_ID [OPTION]コンテナ ファイルコピー
docker cp CONTAINER_ID:CONTAINER_FROM_PATH COPY_TO_PATHDockerfileからイメージ作成
docker build -t NEW_IMAGE_NAME[:TAG_NAME] [OUTPUT_PATH]コマンド挙動差分
イメージ コンテナ コンテナ起動 build ○ × × up ○ ○ ○ start × × ○ run ○ ○ ○
- 投稿日:2019-10-12T18:59:30+09:00
GAE(FE)にDocker環境上のRuby on Railsをデプロイする
はじめに: Dockerで開発したら手軽にデプロイまでしたい。
Ruby on Railsの開発で今や主流のDocker環境。
ネット上に環境構築の情報は豊富に転がっているし、local開発は出来たし、Herokuにもデプロイできた。でもやっぱりHerokuだとイマイチ速度が出ないし、
何よりAWSとかGCP使ってるほうがカッコイイ気がする!(小並感)圧倒的に情報不足なDockerに乗っけたままAWSやGCPにデプロイをする方法。
今回は既にHerokuで運用中のwebサービスをGAE環境に移し替えたのでその際に行った手順と、躓いた点を書いていこうと思います。自分自身も右往左往しながら、なんとかデプロイできたー!!動いたー!!
という感じなので、間違っている点や、改善点などが有りましたら是非色々とご教示いただけると助かります。前提
- 既にDocker+ docker-composeで環境構築済み、動作確認済みのRuby on Railsアプリケーションがある
- GCPアカウント及びプロジェクトが作成済
- Cloud SDKが導入済み
【参考】
Dockerを使ってRuby on Rails環境の構築をしてみる
https://qiita.com/me-654393/items/d11b871ce8d76e153b21Cloud SDK のインストール
https://cloud.google.com/sdk/downloads?hl=jaApp Engineにアプリを作成する
まず最初に、ターミナルからGAEアプリを作成します。
$ gcloud app create You are creating an app for project [project-name]. WARNING: Creating an App Engine application for a project is irreversible and the region cannot be changed. More information about regions is at <https://cloud.google.com/appengine/docs/locations>. Please choose the region where you want your App Engine application located: [1] asia-east2 (supports standard and flexible) [2] asia-northeast1 (supports standard and flexible) [3] asia-northeast2 (supports standard and flexible) [4] asia-south1 (supports standard and flexible) [5] australia-southeast1 (supports standard and flexible) [6] europe-west (supports standard and flexible) [7] europe-west2 (supports standard and flexible) [8] europe-west3 (supports standard and flexible) [9] europe-west6 (supports standard and flexible) [10] northamerica-northeast1 (supports standard and flexible) [11] southamerica-east1 (supports standard and flexible) [12] us-central (supports standard and flexible) [13] us-east1 (supports standard and flexible) [14] us-east4 (supports standard and flexible) [15] us-west2 (supports standard and flexible) [16] cancel Please enter your numeric choice: 2 Creating App Engine application in project [project-name] and region [asia-northeast1]....done. Success! The app is now created. Please use `gcloud app deploy` to deploy your first app.asia-northeast1が東京リージョンですので、選択します。
※[project-name]となっている部分は各々作成したGCPプロジェクト名が入ります。app.yamlを作成する
続いて、Dockerfileと同階層にapp.yamlを作成します。
app.yamlの説明に関してはここでは省略します。
【参考】https://cloud.google.com/appengine/docs/standard/go/config/appref?hl=jaapp.yamlentrypoint: bundle exec rackup --port $PORT env: flex runtime: custom env_variables: SECRET_KEY_BASE: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(各々のsecret key baseを入れる)SECRET_KEY_BASEの取得方法は、
コンソール上で、$ docker-compose exec web bundle exec rails secret表示される文字列をコピペすればOKです。
Railsサーバの起動ポートを8080に合わせる
GAEでは、8080番に対してアクセスするので、3000番などに設定している方は8080番に変更しましょう。
Dockerfile(例)FROM ruby:2.6.3 RUN apt-get update -qq && \ apt-get install -y build-essential \ libpq-dev \ nodejs RUN mkdir /app_name ENV APP_ROOT /app_name WORKDIR $APP_ROOT ADD ./Gemfile $APP_ROOT/Gemfile ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock RUN bundle install ADD . $APP_ROOT # 8080番でポートを起動する CMD /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 8080 -b '0.0.0.0'"docker-compose.yml(例)version: "3" services: web: environment: TZ: Asia/Tokyo build: . volumes: - .:/app ports: - 8080:8080 tty: true stdin_open: true volumes: db-volume:基本的な準備はここまで。
いざデプロイ!
さて、待ちに待ったデプロイ。この瞬間が一番ドキドキします。
ターミナルを開いて、$ gcloud app deploy descriptor: [/project-name/app.yaml] source: [/projects/project-name] target project: [project-name] target service: [default] target version: [20190000t123456] target url: [https://project-name.appspot.com] Do you want to continue (Y/n)? Y(←上記の内容で問題なければ、Yを入力します。)ビルドが始まり、しばらく待ち、
Updating service [default] (this may take several minutes)...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://project-name.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browseと、表示されれば成功。
$ gcloud app browseで確認しましょう。
トラブルシューティング
「Switch to inspect mode.」と怒られる件について
Updating service [default] (this may take several minutes)...failed. ERROR: (gcloud.app.deploy) Error Response: [9] Application startup error: Switch to inspect mode.色々ググったけど今ひとつ情報源に当たれずにめちゃくちゃ困ってた。
8080番でRailsが起動しておらず、GAEがアクセスできていないってことだと思う。原因はdocker-compose側でサーバーを起動していたこと。
docker-compose.yml(例)version: "3" services: web: build: . # ここがアウト command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 8080 -b '0.0.0.0'" volumes: - .:/app_name ports: - "8080:8080" links: - dbこれだとこのエラーが出るみたい。
原因はいまいちよくわかっていないが、もしかしたらdocker-compose読んでいないのかも?8080番ポートの下りで記載したDockerfileのように、
DockerfileCMD /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 8080 -b '0.0.0.0'"で、8080を開いてあげるのがいいのかも。
【参考】
A weekend, a Rails app, a Kubernetes and an Azure.
https://medium.com/@michiels/a-weekend-a-rails-app-a-kubernetes-and-an-azure-d330b003d7c2最後に:Herokuの方がわかりやすいけど、やっぱりGAE早い
今回は実行速度が気になったので、HerokuからGAEに乗り換えることを決意したわけですが、
予想通りGAEの方が速度が出ました。特にRailsの中身をいじること無く、20程度速度が速度が上昇しました。
改善案の部分でサーバー応答時間の短縮(TTFB)が表示されなくなったのがでかい気がします。おまけ:宣伝
今回HerokuからGAEに移行したのはスポチューバーTVという、野球の技術指導メディアです。
スポーツ教育×Techの、主に野球の分野を伸ばしていけたらなと思っているので、興味のある方は是非御覧ください。
https://spotuber-tv.com/参考
- https://medium.com/@michiels/a-weekend-a-rails-app-a-kubernetes-and-an-azure-d330b003d7c2
- https://qiita.com/ClapAndWhistle/items/23e3b4323fd06342b7c4
- https://cloud.google.com/ruby/rails/appengine?hl=ja
- https://qiita.com/takamario/items/33adc033090c31aeb702
- https://qiita.com/kshibata101/items/441de47fcb2d94875e85
- https://qiita.com/shwld/items/e86ee3f642c7857dd56e
- 投稿日:2019-10-12T16:38:47+09:00
DockerやECR, ECS, Fargateなど、コンテナ周りのAWS知識を効率的にキャッチアップしたい人のために
概要
私自身がコンテナや、コンテナ関連のAWSサービスについてはほぼ分からない状態だったのですが、そこからできる限り効率的に知識をキャッチアップしたくて学習したときの道のりです。
同じように困っていらっしゃる方のお役に立てばと思い、記事にしてみました。この道のりの通りに進んでいただければ、時間を無駄にすることなく、多少なりともスムーズに知識をキャッチアップできると思います。
主要な概念や全体像を理解するまでの道のり
いきなり詳細に踏み込んでも、つまりいきなりFargateなどのAWSサービスを使っても、すぐに迷子になることは目に見えていましたので、まずは全体感や重要な概念、用語を理解しようと思いました。
そこで色々と調べていると、次の記事を見つけました。ものすごく分かりやすかったです。
- 「それコンテナにする意味あんの?」迷える子羊に捧げるコンテナ環境徹底比較 (https://dev.classmethod.jp/cloud/aws/cmdevio2019-container/ )
- この記事で紹介されていた以下リンクも、後から読もうと思っています。
- Best practices for writing Dockerfiles(https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ )
- [AWS Black Belt Online Seminar] Docker on AWS レポート [12-factor App](https://dev.classmethod.jp/cloud/aws/black-belt-docker-on-aws-2017/)
これを読んでよく分かったのは、以下の点です。
- レジストリとは、Docker Hubのようなもので、Dockerイメージを管理するところ。AWSだとECRがこれにあたる。
- それとは別次元で、以下がある。
- コントロールプレーン
- コンテナ数の管理など、コンテナの管理をするもの。データプレーンを起動する役割したりする。ECSがこれにあたる。
- データプレーン
- 実際にコンテナが動く場所で、EC2やFargateがこれにあたる。
ただ、上記の記事を読んでも、ECSのクラスター、サービス、タスク、コンテナの概念はよく分かりませんでした。うーむ、難しい・・。
また、それらとデータプレーン(EC2, Fargate)との違いについても、ほぼ理解できませんでした。
こういったトピックについては、以下の記事がとても分かりやすいです。
- Amazon EC2 Container Service(ECS)の概念整理(https://qiita.com/NewGyu/items/9597ed2eda763bd504d7)
DockerコンテナをFargateで動かすことの素晴らしさ
こうやって調査をしていきますと、Fargateというサービスの何が素晴らしいのか、という点が見えてきました。
DockerコンテナをFargateで動かすということは
- PaaS(Elastic Beanstalkなど)よりも自由度が高くなり
- IaaS(EC2など)よりも生産性が高くなる(DockerのインストールやOSセキュリティパッチの適用などから解放される)
ということです。一言でいうと「良い塩梅でめっちゃいい」ということですね。
EC2(つまりIaaS)でコンテナを動かすことはできます。しかし、それにはEC2インスタンスを構築し、Dockerという基盤をインストールする必要があります。そしてOSセキュリティパッチなどの面倒を見続けなければなりません。それは、ものすごく大変なことです。
そのあたりの大変さをAWSが引き受けてくれる、というのがFargateの素晴らしいところです。私たちは、Dockerイメージさえつくれば良いのです。
こういった点から、色々な制約はもちろんあるものの、マネージドの恩恵を最大限に受けるようにした方が得策だと感じてきました。
Dockerfileとdocker-composeの関係
Dockerについてまだ慣れていない私は、この二つの関係がよく分からず混乱していました。
この点については、以下の記事で分かりやすく解説されています。
- Dockerfileとdocker-compose(https://qiita.com/koka/items/3d3d4ee5680f92a0ad89)
実際に動かしてみるまでの道のり
主要な概念や全体像を理解できましたので、今度は実際にECR, ECS, Fargateを使って、Dockerイメージを動かしてみることにしました。
私の場合、自作したアプリを動かしてみたかった関係で、Spring Bootが動くコンテナをつくってみようと思いました。
その際、以下の記事を参考にさせていただきました。
- Docker上でSpring Bootを動かしてみる(https://qiita.com/tkani/items/ed56229330f00a333d5e)
こちらの記事を参考に、以下のDockerfileを、Mavenプロジェクト直下に作成しました。
DockerfileFROM openjdk:8-jdk-alpine COPY target/my-app-0.0.1-SNAPSHOT.jar my-app.jar ENTRYPOINT ["java","-jar","/my-app.jar"]そして、Dockerイメージをつくります。
docker build ./ -t my-app
tオプションは作成したイメージにどんな名前をつけるか、を指定するものです。
ところが、このイメージの名前というものが意外に分かりづらいのです。ここに指定したものは、何を意味するのか、何に影響してくるのかが、分かりません。
tオプションについては、以下の公式リファレンスで解説されています。
- http://docs.docker.jp/engine/reference/commandline/build.html#t
- http://docs.docker.jp/engine/reference/commandline/tag.html
しかし、これらを読んでもイマイチよく分かりません。他の記事を調べても「なるほど!そういうことか!」という思いに至ることができませんでした。
公式リファレンスや先人の解説記事の内容をつなぎ合わせると、イメージ名は以下のものだと分かってきました。
「イメージ名」とは?
イメージ名というのは、全世界のなかでイメージを一意に特定するためのIDみたいなものです。
では、どうやって一意に特定するのかというと
- どのレジストリで管理されているか?
- レジストリ、というのはDockerHubのようにDockerのイメージを管理するところです。
- 平たく言うと、DockerHubなのか?ECRなのか?全く別のホストなのか?、ということです。
- ですから、ここにはホスト名やIPアドレス、およびポート名が記載されることになります。
- そのレジストリの中の、なんというリポジトリなのか?
- リポジトリというのは、レジストリの中にあるもので、Githubのリポジトリのようなものです。
- DockerHubではユーザー名によって名前空間が区切られていますから、ここが[ユーザー名]/[リポジトリ名]という構造になります。一方、そのようにユーザー名で区切られていない場合は、シンプルに[リポジトリ名](スラッシュで区切られない)という感じです。
- そのリポジトリの中の、どのタグか。
- これもGithubのタグと同じようなものです。1.0とかバージョン番号にするのが典型ですね。
docker build -t
のtオプションでタグ名を省略すると、latestがデフォルトで付きます。イメージ名は以上の3要素から構成され、具体的には以下の構造です。
レジストリ名(多くの場合ホスト名)
/リポジトリ名(DockerHubの場合は、「ユーザー名/リポジトリ名」)
:タグ名
では、先ほどように
docker build ./ -t my-app
と指定した場合はどうなるのでしょうか?
ホスト名が省略されていますので、公式リファレンスの
ホストの指定が無ければ、デフォルトで Docker の公開レジストリのある registry-1.docker.io を使います。
の記述に基づいて、
registry-1.docker.io
であると見なされます(つまりDockerHubだと見なされます)。タグ名が省略されていますので、
latest
がデフォルトで指定されます。つまり、以下で指定したのと同じ意味になる、ということだと私は解釈しています。
registry-1.docker.io/my-app:latest
作成したDockerイメージを、ECRに登録します
ローカルPCで先ほどつくったDockerイメージを、ECRに登録していきます。
この手順については公式ガイドで解説されています。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html#use-ecr以下、この公式ガイドの手順どおりに実行したことについて、解説してきます。
ECRでは、レジストリはユーザー単位に作成されます。ここはDockerHubとは異なりますね。DockerHubは全体で一つのレジストリで、その中の名前空間をユーザー名で分割してる感じです。
ですので、どのレジストリにアクセスするかは、aws cliでログインしているユーザに紐づくレジストリとなります。このため、コマンドにはレジストリを指定する内容が出てきません。
まずは、レジストリという自分専用の部屋に、今回のDockerイメージを格納するための空間(リポジトリ)を作成します。
aws ecr create-repository --repository-name my-app --region ap-northeast-1
すると、以下の結果がかえってきます。
{ "repository": { "repositoryArn": "arn:aws:ecr:ap-northeast-1:{アカウントID}:repository/my-app", "registryId": "{アカウントID}", "repositoryName": "my-app", "repositoryUri": "{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app", "createdAt": 1570824304.0 } }
次に、リポジトリーに登録したDockerイメージに、ECR用のイメージ名(tag)をつけます。
docker tag my-app {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app
ここでついに、イメージ名にホスト名を明示的に追加したわけです。
{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com
というECR上の私専用の部屋(レジストリにある、my-app
というリポジトリに配置するイメージだよということを、イメージ名が表しています。なお、タグについては省略しましたので、自動的に「latest」が付与されます。
次に、レジストリ(ECR)にログインする必要があるのですが、「ログインするためのコマンド」を取得するためのコマンドを叩かねばなりません。
aws ecr get-login --no-include-email --region ap-northeast-1
すると、以下のコマンドを実行するよう、指示されます。
docker login -u AWS -p {ものすごく長い文字列。12 時間有効な認証トークン、つまりパスワード。} https://{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com
このコマンドを実行してECRにログインします。
そして、さきほどつけたタグ名を指定して、ECRにイメージを登録します。
docker push {アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app
The push refers to repository [{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app] ffb5690b4e55: Preparing ceaf9e1ebef5: Preparing 9b9b7f3d56a0: Preparing f1b5933fe4b5: Preparing no basic auth credentials
このようにno basic auth credentialsが出てしまった場合は、以下を参考に対応しましょう。
https://qiita.com/NaokiIshimura/items/1886dbd04631c3f7d0e1うまくいくと・・・
The push refers to repository [{アカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app] ffb5690b4e55: Pushed ceaf9e1ebef5: Pushed 9b9b7f3d56a0: Pushed f1b5933fe4b5: Pushed latest: digest: sha256:{ハッシュ値} size: 1160
のようになります。
管理コンソールから見ると・・・
しっかり登録されています!よかった!
ECRに登録したDockerイメージを、ECSを使ってFargateの上で動かします。
次は、このECRに登録したdockerイメージを、Fargateの上で動かしてみましょう。Fargateで動くDockerコンテナの管理は、ECSで行います。
この手順については、公式ガイドで解説されています。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ECS_GetStarted_Fargate.htmlガイドに記載のとおり、以下ウィザードを使ってECSおよびFargateをセットアップできます。
https://console.aws.amazon.com/ecs/home#/firstRun私が分かりづらかった点を、以下に記載します。
ポートマッピング
ポートマッピングをSpring Boot(のtomcat)が待ち受けているポート番号に指定します。たとえば、Tomcatが5000番ポートをリッスンする設定にしているならば、5000を指定する必要があります。Fargateをつかう場合、前面で待ち受けるポートと、コンテナ側のポート番号は同じじゃないとダメみたいです。それはもはや「マッピング」ではないと思いますが・・。
セキュリティグループのインバウンドルール
ポートマッピングでFargateが待ち受けるポート番号を、Tomcatが待ち受けるポート番号と同じにしないといけないので、そのポート番号でFargateへ流入してくるトラフィックを許可しないといけません。
Fargateから他のAWSサービスを呼び出す場合は、権限設定が必要
権限がない状態でAWSサービスを呼び出すと、エラーが起こります。今回のアプリの場合、Fargateで動くSpring Bootアプリから、DynamoDBを呼び出していました。
ECSの管理コンソールからログが見れるのですが、そこでログを見て見ると・・・
Caused by: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), com.amazonaws.auth.profile.ProfileCredentialsProvider@46393853: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@53f52e4e: Unable to load credentials from service endpoint]
というエラーが出ていました。
↓整形すると・・・
Caused by: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [ EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), com.amazonaws.auth.profile.ProfileCredentialsProvider@46393853: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@53f52e4e: Unable to load credentials from service endpoint ]
これを素直に読めば「どこかにcredentialを置け」、と指示されていることになります。
しかし、その前にそもそも、EC2やFargateからAWSのAPIを呼び出すときは、どのユーザーのAWS_ACCESS_KEY_IDとAWS_SECRET_KEYを指定すべきなのでしょうか?
普通に考えたら、サーバーや設定画面に、アクセスキーやシークレットキーを配置するなど、セキュリティ的に考えられませんから、実行しているFargate, EC2のロールに権限をつけることで対象のサービスを呼び出したいところです。
先ほどのエラーも、タスクを実行するロールに、対象のAWSサービス(今回はDynamoDB)にアクセスする権限が付与されていないため、しょうがなくどこかにアクセスキーなどを探しにいったところ、見つからなかった、という顛末でしょう。
ということで、そもそもタスクを実行するロールに適切な権限さえついていれば、問題がないということです。
これを実現するには、ECSのタスク定義でタスクロールを適切に設定すれば良いです。
私の場合は、この「タスクロール」に何のロールも設定されていませんでした。ecsTaskExecutionRoleはデフォルトで用意されているもののようで、ひとまずこのロールを設定します。
あとは、対象のAWSサービスを呼び出す権限を、このロールに付与すればOKです。
ecsTaskExecutionRoleのリンクから、ロールの設定画面に飛べます。
私の場合は、Fargateで動かすコンテナからDynamoDBを使いたいので、ここにAmazonDynamoDBFullAccessを付与してみました。(権限が強すぎるとは思いますが・・)
すると、先ほどのエラーも出ず、通常どおりに動作しました!
終わりに
以上、私のキャッチアップの道のりをご紹介しました。
aws cliの導入手順などは端折ってしまいましたが、誰かのお役に立てたらと思います。
ご覧いただき、ありがとうございました。
- 投稿日:2019-10-12T16:10:36+09:00
IntelliJ + Docker + Pythonの環境構築
はじめに
Macbookを買い換えたのでPythonの開発環境を作り直すことになるのですが、ローカルに直接Pythonをインストールすると、ついうっかりglobalにパッケージをインストールしてしまったり、venvを使っていても環境を作り直したいときに一手間が面倒だったり、ということが嫌だったのでDockerを使って構築することにしました。
IntelliJにPluginインストール
IntelliJにDocker Pluginが入っていない場合は
Preferences > Plugins
からインストールします。Pythonプロジェクトの作成
次にIntelliJを立ち上げてPythonプロジェクトを作成します。
Dockerの必要なイメージはこの後作るので、ここではとりあえず適当なProject SDKを選んでおきます。(ここではPython2.7(venv)になっています)
それ以外はデフォルトのままで良くて、プロジェクトを作成します。IntelliJ上でDockerfileを作成してイメージをビルドする
今回はPythonQiitaというプロジェクト名にしました。最初にPython環境をDockerイメージにしておく必要があるので、プロジェクトフォルダの直下に
Dockerfile
を作成します。(場所はどこでも良い)Dockerfileにはベースとなるイメージファイル、初期設定コマンドなどを書いておきます。
今回はpython:3
イメージを使います。パッケージにpandas
numpy
を入れておきます。作成したDockerfileを右クリックして、メニューから
Create Dockerfile
を選択します。Configurationウィンドウが表示されるので
Image tag
を入力します。このタグ名は後で使います。ここではpython_qiita
としました。
Run built image
のチェックは外しておきます。これをオンにしておくと、イメージをビルドした後、コンテナとして起動してくれます。Container name
を入力すると、そのコンテナ名で起動するようになっています。下記のから作成したDockerfile設定を起動すればイメージがビルドされます。Deploy Logに
'python_qiita Dockerfile: Dockerfile' has been deployed successfully.
と出て完了したことが分かります。イメージが作成されるとServicesビューにイメージ名が表示され、ビルドが成功したことが分かります。
ビルドしたイメージをProject SDKとして設定する
Dockerイメージがビルドできると、プロジェクトで利用するSDKとして利用できるようになります。コンテナはSDKにはならないので注意が必要です。
FIle > Project Structure
を開き、Project項目にあるNew
ボタンを押し、ポップアップにあるPython SDK
を選択します。
Python Interpreterを選択するウィンドウが表示されるので、左メニューにある
Docker
を選びます。すると、Image nameに先ほどビルドしたDockerイメージのタグ名が選択できるようになっていることを確認してOKボタンを押します。Project StructureのSDKs項目に
Remote Python 3.7.4 Docker...
が表示されており、packagesにDockerfileに書いたパッケージがインストールされていることが分かります。venvなどの環境では、ここでパッケージの追加・削除ができますが、DockerイメージのPythonだと追加・削除はできません。パッケージの構成が変わるたびにイメージをビルドしなおす必要があります。Pythonの実行とデバッグ
ここまでくれば後は通常通りPythonファイルを作成して実行するだけですが、、、
設定を完了した直後だと、IntelliJがPythonの構成を適切に読み込めていないらしく、一度プロジェクトを閉じて開きなおす必要があります。さらに、画面下に下記のような更新中のインジケータが完了するまで待たないといけません。ここだけが難点です。仕組みはわかりませんが、改善されることに期待したいですね。ここまで出来ればPythonのコード補完や実行、デバッグがIntelliJ上でできるようになっています。下記はpandasをインポートして実行した状態。
不便なこと
環境はDockerで構築できるのでポータブルになるし、気軽に作り直せることは実行環境面で非常に便利に感じます。一方で、いくつか不便に思うことがあるので書いておきます。
Dockerイメージをビルドしなおすと構成読み込みに時間がかかる
上述のSDKを設定した直後と同様に、イメージをビルドし直してPythonパッケージの構成を変えたとしても、すぐに反映されません。プロジェクトを再起動するなどして、IntelliJが再認識するのを待つ必要があります(数分)。
構成見直しが不要になってくると気になりませんが、プロジェクトの初期フェーズでは煩わしいです。matplotlibなどの
show()
的なことができない当たり前ですが、Docker上で実行するので
show()
のようなウィンドウを立ち上げることができません。諦めてファイルに保存して確認するしかないです。まとめ
紹介したような不便なところもありますが、環境も汚れないしポータブルであることは便利だと感じています。今までだと、パッケージの再構築が面倒だったり、requirements.txtのようなものに書きださなければならなかった環境が、Dockerfileにまとまるし、必要ならイメージをレポジトリで保存しておく事もできるのは良い感じだなと。
venvとどちらが楽か、と聞かれるとvenvだと思いますが、新しい環境で色々とやってみる方が今の自分の好みに合っているので、暫くはDockerで進めてみようと思います。
- 投稿日:2019-10-12T15:18:03+09:00
Docker環境でAtCoder〜Ruby編
AtCoderのRuby環境って特殊だよね?
AtCoderのRubyのバージョンは2.3.3です。ちょっと古いですね。AtCoderの時だけrbenvを使って2.3.3に戻してもいいですけど、Dockerを使ってもいいなぁとぼんやり思っているここの私!
というわけで、DockerでRubyのAtCoder環境を整えてみました。Dockerfileを書いてみた
DockerfileFROM ruby:2.3.3 ENV LANG="C.UTF-8" ENV USER yourname ENV HOME /home/${USER} RUN useradd -m ${USER} RUN gpasswd -a ${USER} sudo RUN echo "${USER}:password" | chpasswd RUN gem install at_coder_friends USER ${USER} WORKDIR ${HOME} CMD ["/bin/bash"]途中でインストールしているgemの
at_coder_friends
というのは、 AtCoderツールを自作した話 で @nejiko96 さんが作ってくださったAtCoderのテストツールです。テストだけではなく、回答のスケルトンも作ってくれたり、このツールから回答フォームにsubmitできたりとものすごく便利です。現在はRubyとC++に対応している模様です。
Usageなどが書かれたGitHubのリポジトリはこちら> AtCoderFriendsで、ビルドして実行してAtCoderを楽しみましょう!
docker build --tag at-coder . docker run --rm -it -v path/to/atcoder_problems:/home/yourname at-coder参考URL
https://qiita.com/Riliumph/items/3b09e0804d7a04dff85b
https://qiita.com/nejiko96/items/0cd23ac2c033864ef341
- 投稿日:2019-10-12T14:52:17+09:00
dnmonsterで生成した画像データをiterm2上で表示してみる
dnmonsterとは
githubの初期アイコンなどのランダムな画像はindenticonと呼ばれるみたい。
dnmonsterはindenticonを生成して返却してくれるNode.jsで作られたwebサーバ。
amouat/dnmonster: Dockerised Node server for KevinGuadin's monsterids
モンスターがかわいい。実行環境
- macOS Mojave
- iterm2
- docker
試してみる
$ docker run -d -p 8000:8080 amouat/dnmonster $ curl http::/localhost:8000/monster/sk8metal �PNG bKGD�������oIDAT8�c`C�\����*��Ĩe"d1bD� �lb耑�!��X�b�2�a���D{�[葁.��P g���^�zb$֕� řa��E .��t!�+a��Q@]��R�\]��IEND�B`�%PNGの画像データとして返ってきた。
imgcatを用意する
iterm2で画像を表示するためにimgcatを用意する。
$ cd /usr/local/bin;wget "https://www.iterm2.com/utilities/imgcat";sudo chmod +x imgcatdnmonsterから返却された画像データを表示してみる
imgcatを利用してdnmonsterから返却された画像データをiterm2上で表示してみる。
$ curl http:/localhost:8000/monster/sk8metal | imgcat
参考
- 投稿日:2019-10-12T13:20:36+09:00
【図解付き】Docker Data Volumeのバックアップ・リストア方法
バックアップ方法
$ docker run --rm --volumes-from [データボリュームのマウント先コンテナ名] -v `pwd`:/backup busybox tar cvf /backup/backup.tar [データボリュームのマウント先ディレクトリ]もしくは
$ docker run --rm -v [データボリューム名]:[データボリュームのマウント先ディレクトリ] -v `pwd`:/backup busybox tar cvf /backup/backup.tar [データボリュームのマウント先ディレクトリ]具体例
MySQLのデータベース情報が保存されているデータボリュームをバックアップしたい場合は以下のようになります。
データボリュームがマウントされているDBコンテナをwp_db_con
とします。$ docker run --rm --volumes-from wp_db_con -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/mysql図で表現すると以下のようになります。
もしくは以下のようになります。
データボリューム名をmy_wordpress_mysql_data
とします。$ docker run --rm -v my_wordpress_mysql_data:/var/lib/mysql -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/mysql図で表現すると以下のようになります。
リストア方法
$ docker run --rm --volumes-from [データボリュームのマウント先コンテナ名] -v `pwd`:/backup busybox tar xvf /backup/backup.tarもしくは
$ docker run --rm -v [データボリューム名]:[データボリュームのマウント先ディレクトリ] -v `pwd`:/backup busybox tar xvf /backup/backup.tar具体例
MySQLのデータベース情報が保存されているデータボリュームをリストアしたい場合は以下のようになります。
$ docker run --rm --volumes-from wp_db_con -v `pwd`:/backup busybox tar xvf /backup/backup.tarもしくは以下のようになります。
$ docker run --rm -v my_wordpress_mysql_data:/var/lib/mysql -v `pwd`:/backup busybox tar xvf /backup/backup.tarさいごに
データボリュームのバックアップ・リストア方法の詳細については【Docker】具体例で理解するデータボリュームのバックアップ・リストア方法でも紹介していますのでもし興味のある方はご覧になっていただければと思います。
ツイッター(@nishina555)やってます。フォローしてもらえるとうれしいです!
- 投稿日:2019-10-12T00:35:04+09:00
Docker上で自前OpenSSH(sshd)をビルドして動そうとしてコケた話
何がしたかったか?
- 研究関連でOpenSSH(のsshd)を自前でビルドして色々試したい事がある
- Mac上でうまくビルドできないし,どこでもビルドできるようにDockerで動かしたい
- つまりDocker上でビルド,サービス化,接続テストができるように
- MacのVSCodeで編集,即座にDocker上でビルド,すぐ接続テスト.したい.
- DockerといえばAlpine Linux!!
環境とか
- Docker Engine: 19.03.2
Docker Compose: 1.24.1
ディレクトリ構造
tree.txt. ├── docker-compose.yml ├── src │ └── OpenSSHのソースコード └── vm ├── Dockerfile └── login.sh最初に試したこと
1. 以下のdocker-composeとDockerfileを書いてみた.
docker-compose.ymlversion: '3' services: sshd-build: build: ./vm # vm/Dockerfileがあるのでそいつをビルド image: sshd-build:latest container_name: sshd-container restart: always volumes: - ./:/root/openssh-portable # ローカルで開発してDockerでビルド,検証したいので共有 tty: true # 立てたコンテナの中で動きたいときに書くやつDockerfileFROM alpine as sshd-linux WORKDIR /root # rootとして動くのでここを作っとく RUN apk update && \ # ビルドに必要なパッケージの追加 apk add --no-cache openrc openssh \ # この2つはAlpineのデーモン登録のため必要 gcc g++ make openssl-dev zlib-dev bash # これらはビルドのため ENTRYPOINT ["/bin/bash"]2. コンテナへのログイン
login.sh#!/bin/bash docker exec -it sshd-container /bin/bash3. ビルドとインストール
# cd openssh-portable/src # ./configure && make && make install問題とその解決
1. インストール後, デーモン起動を試みるも...
tty# rc-service sshd start /lib/rc/sh/openrc-run.sh: line 100: can't create /sys/fs/cgroup/blkio/tasks: Read-only file system /lib/rc/sh/openrc-run.sh: line 100: can't create /sys/fs/cgroup/cpu/tasks: Read- ... 同様の表示 * You are attempting to run an openrc service on a * system which openrc did not boot. * You may be inside a chroot or you may have used * another initialization system to boot this system. * In this situation, you will get unpredictable results! * If you really want to do this, issue the following command: * touch /run/openrc/softlevel * ERROR: sshd failed to start起動できていない...ここは海外ニキを参考にして修正をした.海外ニキ,全体的にエスパーで解決しに来るのでつよい.
今回環境の場合はdocker-composeを使っているのでそこに追加.2. その後も追加でエラー...
- 後半のエラーコード(
You are attempting...
)は消えず.エラーコードに従って
touch /run/openrc/softlevel
を叩いたら通った.結論
docker-compose.ymlversion: '3' services: sshd-build: build: ./vm image: sshd-build:latest container_name: sshd-container restart: always volumes: - ./:/root/openssh-portable - /sys/fs/cgroup tty: trueDockerfileFROM alpine as sshd-linux WORKDIR /root RUN apk update && \ apk add --no-cache openssh openrc gcc g++ make openssl-dev zlib-dev bash ENTRYPOINT ["/bin/bash"]コンテナ起動後
# cd openssh-portable/src # ./configure && make && make install # touch /run/openrc/softlevel # rc-service sshd start ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519 * Starting sshd ... [ok] # rc-status Runlevel: sysinit Dynamic Runlevel: hotplugged Dynamic Runlevel: needed/wanted Dynamic Runlevel: manual sshdあとはソースコード書き換えて,
make && make install && rc-service sshd restart
を繰り返す.ちなみに
イメージサイズは197MBであった.もう少し小さくしたいな...
その話はまた今度.あとビルドが遅い.数秒で終わってほしい(願望)