- 投稿日:2020-03-05T22:21:00+09:00
dockerでpythonを使う
docker pull python docker run --name python -i -t python /bin/bash参考
https://dev.classmethod.jp/cloud/aws/win10_docker_python_ecs_cfn/
https://qiita.com/chroju/items/ce9cae248cc016745c66
- 投稿日:2020-03-05T17:33:29+09:00
laradockで作成したプロジェクトがgithubで開けない
こちらの記事を参考に環境構築
LaradockをWindows 10 Homeにインストールデイレクトリ構成はこんな感じ
laradockpjt/
├app(laravelのプロジェクト)
├laradockローカルでの環境構築を終えてgithubにpush
しかしlaradockpjt直下のappフォルダが開けない(非活性?になってる)
原因
最初にlaradockをsubmoduleとしてクローンしてない
(gitのサブモジュール機能に関して全くの無知だった…)git clone -b LaraDock-ToolBox https://github.com/LaraDock/laradock.git //こっちだと開けない git submodule add https://github.com/LaraDock/laradock.git //こっちのコマンドでlaradockをサブモジュール化後は手順通りに進めるとOK!
すでに環境構築済みだったので巻き戻しにかなり時間食ってしまった…
- 投稿日:2020-03-05T15:29:15+09:00
Docker② DockerでLaravel環境構築
Dockerを使ったLaravel開発環境構築
目次
- 環境準備
- ディレクトリ作成
- docker-compose.yml作成
- Dockerfile作成
- PHP設定ファイル作成
- Nginx設定ファイル作成
- Laravelプロジェクト作成
- 動作確認
参考
環境準備
どうせなので、まっさらのEC2でやってみた方が良いかなと。
最低限何が必要なんだ?ってことで前回のおさらいをしてみたけど、こんな感じか。Dockerインストール # sudo amazon-linux-extras install docker Dockerサービス起動 # systemctl start docker.service サービスの起動確認 # systemctl status docker Dockerの自動起動設定 # systemctl enable docker 試しにDockerコマンド実行 # docker infoDocker Composeインストール # curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose Docker Composeのインストールを確認 # docker-compose --version docker-compose version 1.21.2, build a133471これで大丈夫そうだった。余裕っすね。
ディレクトリ作成
以下の構成を想定しています。
project
├ docker-compose.yml
├ docker
│ ├ php
│ │ ├ php.ini
│ │ └ Dockerfile
│ └ nginx
│ └ default.conf
└ serverとのこと。(太字はディレクトリ)
# cd /var # mkdir project # mkdir project/docker project/server # mkdir project/docker/{php,nginx} # ll -d `find ./project` drwxr-xr-x 4 root root 34 Mar 5 02:51 ./project drwxr-xr-x 4 root root 30 Mar 5 02:52 ./project/docker drwxr-xr-x 2 root root 6 Mar 5 02:52 ./project/docker/nginx drwxr-xr-x 2 root root 6 Mar 5 02:52 ./project/docker/php drwxr-xr-x 2 root root 6 Mar 5 02:51 ./project/server別にvarじゃなくてもいいけど、なんとなくvarで。
docker-compose.yml作成
docker-composer.ymlversion: '3' services: php: container_name: php build: ./docker/php volumes: - ./server:/var/www nginx: image: nginx container_name: nginx ports: - 80:80 volumes: - ./server:/var/www - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - php db: image: mysql:5.7 container_name: db-host environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: database MYSQL_USER: docker MYSQL_PASSWORD: docker TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./docker/db/data:/var/lib/mysql - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf - ./docker/db/sql:/docker-entrypoint-initdb.d ports: - 3306:3306こんな感じにするらしい。
中身について考えてみる。php
php: container_name: php ① build: ./docker/php ② volumes: - ./server:/var/www ③① コンテナの名前
② ./docker/phpにあるDockerfileを参照する
③ ホスト側の./serverと、コンテナ側の/var/wwwをマウントnginx
nginx: image: nginx ① container_name: nginx ② ports: - 80:80 ③ volumes: - ./server:/var/www ④ - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf ⑤ depends_on: - php ⑥① Dockerイメージの指定
② コンテナの名前
③ PORTを指定
④ ホスト側の./serverと、コンテナ側の/var/wwwをマウント
⑤ ホスト側のdefault.confを、コンテナ側にコピー(マウント?)
⑥ 依存関係を指定。この場合、nginxを実行する前にphpw実行する。db
db: image: mysql:5.7 ① container_name: db-host ② environment: MYSQL_ROOT_PASSWORD: root ③ MYSQL_DATABASE: database ④ MYSQL_USER: docker ⑤ MYSQL_PASSWORD: docker ⑥ TZ: 'Asia/Tokyo' ⑦ command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ⑧ volumes: - ./docker/db/data:/var/lib/mysql ⑨ - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf ⑩ - ./docker/db/sql:/docker-entrypoint-initdb.d ⑪ ports: - 3306:3306 ⑫DBに関しては、実際はRDSを使用したい。
現時点ではとりあえずコンテナを作成して使用する。① Dockerイメージの指定
② コンテナの名前
③~⑦
諸々の環境変数。
別ファイルに記載して「env_file: .env」みたいに指定することも可能。
(というかセキュリティ面とか考えたらその方が良いのでは)
⑧ デフォルトのコマンドを上書きする、らしい。
⑨~⑪
諸々のマウント
⑫ PORTを指定Dockerfile作成
phpコンテナの構築時に、以下のDockerfileを使用する。
DockerfileFROM php:7.2-fpm COPY php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y zlib1g-dev mariadb-client \ && docker-php-ext-install zip pdo_mysql #Composer install RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { 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 /composer ENV PATH $PATH:/composer/vendor/bin WORKDIR /var/www RUN composer global require "laravel/installer"各行の処理については、Dockerfileリファレンスを参照。
php.ini作成
phpの設定ファイル。
php.ini[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese"default.conf作成
nginxの設定ファイル。
default.confserver { listen 80; index index.php index.html; root /var/www/public; location / { root /var/www/public; index index.html index.php; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }Laravelプロジェクト作成
docker起動 # docker-compose up -d ERROR: Service 'php' failed to build: The command '/bin/sh -c php composer-setup.php' returned a non-zero code: 1こけた。
こけたら元に戻してくれるのかと思いきや、戻らないみたい。イメージ一覧を表示 # docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 4744417607b3 10 minutes ago 472MB php 7.2-fpm 6ff5bc1d81f0 7 days ago 398MBどこでこけたんだろう。
と思って、元の記事のコメント見てみた。自分と同じようにComposerのインストールで引っかかった方は、
最新のハッシュ値を下のサイトで確認して書き換えると上手くいくと思います。
https://getcomposer.org/download/ふむふむ、確かにリンク先確認したらハッシュ値が違った。
※ていうか、べた書きなことに少し疑問盛ってたけど、ちゃんと追っておけばよかった。Composerのインストールはバージョンによってハッシュ値が異なってしまう関係上、毎回Dockerfileを書き換えのは面倒なので以下の書き方をすると書き換える必要がなくて便利です!
# 変更前 RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { 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 # 変更後 COPY --from=composer:latest /usr/bin/composer /usr/bin/composerなにこれ天才かよ。。。
DockerfileFROM php:7.2-fpm COPY php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y zlib1g-dev mariadb-client \ && docker-php-ext-install zip pdo_mysql #Composer install COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin WORKDIR /var/www RUN composer global require "laravel/installer"すっきりした。
もう一回実行してみる。docker起動(2回目) # docker-compose up -d ERROR: Service 'php' failed to build: The command '/bin/sh -c composer global require "laravel/installer"' returned a non-zero code: 1こけたけど、さっきよりは処理進んでるっぽい。
赤字の部分にこんなのがあった。[ErrorException] proc_open(): fork failed - Cannot allocate memoryこれ、知ってるぞ
Docker云々の前、普通にLaravelデビューするときに出てきた。
その時と同じ状況でやってるんだから、同じことが起きても不思議じゃないよね。https://akamist.com/blog/archives/236
以前はここに記載の方法「Swap領域の有効化」でうまくいったけど、Dockerでやってる今はどうなんだろう。
試しにやってみる。# /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 14.0341 s, 76.5 MB/s # /sbin/mkswap /var/swap.1 mkswap: /var/swap.1: insecure permissions 0644, 0600 suggested. Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes) no label, UUID=672b24c0-04f2-4b5b-b6ce-b3bd6ad3a764 # /sbin/swapon /var/swap.1 swapon: /var/swap.1: insecure permissions 0644, 0600 suggested.準備OK。いざ。
docker起動(3回目) # docker-compose up -d (略) Creating php ... done Creating db-host ... done Creating nginx ... done # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c111408c89a5 nginx "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp nginx 1d5bc8716afa mysql:5.7 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp db-host 94d3abb55903 project_php "docker-php-entrypoi…" 2 minutes ago Up 2 minutes 9000/tcp php 93eae4fcf1cc f959b6f2dc70 "/bin/sh -c 'compose…" 12 minutes ago Exited (1) 11 minutes ago upbeat_saha 7e3ab5b0fb47 4744417607b3 "/bin/sh -c 'php com…" 45 minutes ago Exited (1) 45 minutes ago sleepy_hellman ※下の2つはこけた時のなので、後で消した脳汁☆全開
続きもやっていこう。
phpコンテナに入る # docker-compose up -d root@94d3abb55903:/var/www# Laravelプロジェクト作成 # laravel new (略) Application ready! Build something amazing.さっくりと成功しました。
動作確認
事前にEC2のセキュリティグループに手を加えておくのを忘れない。
こけた。
(画面とりわすれちゃったけど)LaravelのPermission Denied的なやつがでてくる。Laravelまわりのディレクトリのパーミッション変更が必要だった。
「これってセキュリティ的にどうなの?」とは思う。
けど現段階ではまだそこまで考えなくていいので、無心で変えていく。# sudo chmod 2775 /var/project/server # find /var/project/server -type d -exec sudo chmod 2775 {} + # find /var/project/server -type f -exec sudo chmod 0664 {} + # sudo chmod -R 777 /var/project/server/storage/ # sudo chmod -R 777 /var/project/server/bootstrap/cache
- 投稿日:2020-03-05T10:27:13+09:00
【Rails不定期連載】#1 DockerでRailsの環境構築
アウトプットの練習 & 初心に帰って基礎からRailsを見直してこうと思います。
不定期に更新します。今回はRuby on Railsの環境構築。
今回はDockerでRailsチュートリアルを進めていくためのRailsプロジェクトを作ります。
rbenvなどを用いたローカルでの環境構築ではないです。前置き
前提として...
- 以下の場合はローカルでの環境構築を勧めます
- railsの環境構築1度もしたことない
- dockerを使った開発をしたことがない(Dockerfileの記述がわからない) ### アプリケーション要件
- ruby 2.6.5
- rails 6.2.0
- sqlite3
- webpacker、springはとりあえず不要なので除く
すごいざっくりですが、こんなイメージ、コンテナを作るのがゴールです。
レッツ環境構築
STEP1 rails newコマンドまでの準備
PJ用のディレクトリを作成してその中で作業していきます。
まずは必要になるファイルを用意しましょう。
touch Dockerfile docker-compose.yml Gemfile Gemfile.lock .gitignore
Gemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.5' gem 'rails', '~> 6.0.2', '>= 6.0.2.1'DockerfileFROM ruby:2.6.5-alpine ENV LANG="C.UTF-8" \ PACKAGES="curl-dev build-base alpine-sdk tzdata sqlite-dev less ruby-dev nodejs" RUN apk update && \ apk add --no-cache --update $PACKAGES WORKDIR /var/www COPY ./ ./ RUN gem install bundler && \ bundle install -j4 EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]docker-compose.ymlversion: '3' services: app: build: context: ./ dockerfile: Dockerfile volumes: - ./:/var/www ports: - "3000:3000" tty: true stdin_open: true restart: always.gitignore# Ignore bundler config. /.bundle # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal /db/*.sqlite3-* # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # Ignore uploaded files in development. /storage/* !/storage/.keep /public/assets .byebug_history # Ignore master key for decrypting credentials and more. /config/master.key .idea .vscode .DS_store一旦ここまで作ってしまいます。
(.gitignoreはお好みあれば)ここまで作ったらイメージを作成します。
docker-compose build
STEP2 Railsプロジェクトの作成、微修正
buildが完了したら、いよいよRailsプロジェクトを作成します。
-d sqlite -> 使用DBをsqlite3を選択
-B -> プロジェクト作成後のbundle installをしない(修正するからスキップで)
--skip-webpack-install -> プロジェクト作成後のwebpacker:installをしない
--skip-spring -> プロジェクト作成後のspringのinstallをしない
docker-compose run --rm app rails new -d sqlite3 -B --skip-webpack-install --skip-spring .
コマンド実行すると、いくつかのファイルがもう存在するけどどうする〜?みたいに聞かれます。
.gitignoreファイルは上書きなし、Gemfileは上書きしてしまいましょう。conflict .gitignore Overwrite /var/www/.gitignore? (enter "h" for help) [Ynaqdhm] n skip .gitignore conflict Gemfile Overwrite /var/www/Gemfile? (enter "h" for help) [Ynaqdhm] Y force GemfileGemfileにあるwebpackerの記述を消しましょう
Gemfile# 下記二行を削除 # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0'サーバー立ち上げた後にsw.jsが無いとエラーを吐きまくるので仮で作っておきましょう。
touch public/sw.js
ここまでくればもう少し、bundle installとdbの作成、マイグレーションを実行します。
その前にgemを更新するため、再度ビルドしてあげましょう。
docker-compose build
docker-compose run --rm app rails db:create
docker-compose run --rm app rails db:migrate
STEP3 Railsプロジェクトの起動
あとはコマンド一つでRailsサーバーが立ち上がります。
docker-compose up -d
http://localhost:3000 で立ち上がるのを確認しましょう。
やったぜ。
終わりに
出来上がりのソースコードはこちらに置いてあります。(変更あるかもしれませんが)
RubyMineを最近購入したのでこれからウッキウキでコード書こうと思います。
Railsに関しての記事をこれから不定期ですが粛々とアップしていきますのでよければ!
- 投稿日:2020-03-05T07:59:21+09:00
DockerでNGINX + NGINX Unit + MySQLの環境を構築
Dockerの導入
以前、NGINX + NGINX Unit + Flaskの環境を構築しました。
NGINX + NGINX Unit + Flask で PythonのWeb アプリを動かす
前回はVagrantとVirtualBoxで構築しましたが、今回はDockerで構築していこうと思います。
前回と同様に、WebサーバーにNGINX
を、APサーバーにNGINX Unit
を、フレームワークにFlask
を使用します。
更に今回はデータベースとしてMySQL
を追加し、WEB <-> AP <-> DB
の環境を構築をしていきます。以下の図のようなイメージです。(本来コンテナはホスト内で起動しますが、わかりやすように分けています)
順を追って構築していくため、できたものをみたい方はGitHubに上げてありますのでそちらをどうぞ。
https://github.com/txkxyx/docker-web
環境
以下の環境で構築していきます。
- ホスト
- OS : macOS Catalina 10.15.3
- Docker : 19.03.5
- コンテナ
- Python : 3.7.3
- Flask : 1.1.1
- NGINX : 1.17.7
- NGINX Unit : 1.14.0
- MySQL : 8.0.18
- Flask SQLAclchemy : 2.4.1
ディレクトリ構成は以下のようにします。
./web |- db // DB用 |- nginx // NGINX用 |- python // NGINX Unit・ソースファイル用 | |- src |- docker-compose.yml
では始めていきます。
Dockerfiletとdocker-composeの設定値
Dokerfileとdocker-composeで使用する設定値を簡単にまとめておきます。
Dockerfileの設定値
詳しくは公式のDockerfileリファレンスを参照してください。
https://docs.docker.com/engine/reference/builder/
設定値 概要 FROM 使用するイメージを指定する。 WORKDIR 作業ディレクトリを指定する。この宣言以降はコンテナ内の指定したパスで作業を行う。 COPY ホストからコンテナに、指定したディレクトリやファイルをコピーする。 ホスト コンテナ
の順で指定する。.dockerignore
で指定したファイルは対象外となる。RUN 指定したコマンドを現時点のコンテナ内で実行する。(ビルド時に実行するコマンド) CMD コンテナ起動時に実行するコマンドを指定する。(起動時に実行するコマンド) docker-composeの設定値
詳しくは公式のリファレンスを参照してください。
https://docs.docker.com/compose/compose-file/
設定値 概要 version Docker Engineが対応するファイルフォーマットのバージョン services アプリケーションを構成する各要素 build 起動するコンテナの Dockerfile
があるディレクトリを指定。子要素で、context(DockerfileのあるディレクトリまたはGithubURL)args(Dockerfileに渡す引数)などを指定できる 。image 起動するコンテナが使用するイメージを指定する。 command docker-compose up を実行した際に実行されるコマンド ports コンテナが公開するポートを指定します。 ホスト:コンテナ
もしくはコンテナのポートのみ指定します。expose リンクするコンテナのみに公開するコンテナのポートを指定します。ホストには公開されません。 environment 起動するコンテナの環境変数を指定します。 volumes コンテナにマウントするホストのディレクトリを指定します。 ホスト:コンテナ
の形式でパスを指定します。container_name 起動するコンテナのコンテナ名を指定します。 depends_on サービス間の依存関係を指定します。指定したサービス名が先に起動します。 DBコンテナの構築
まずはMySQLのコンテナを構築していきます。
イメージはこんな感じです。
docker-compose.yml
を作成します。web/docker-compose.ymlversion: "3" services: db: image: mysql command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ports: - "33306:3306" expose: - "3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: test MYSQL_PASSWORD: test volumes: - ./db/init:/docker-entrypoint-initdb.d container_name: app_dbコンテナの初期起動時にデータベースを作成するように、
db
ディレクトリ内にinit
ディレクトリを作成し、createdatabase.sqlを作成します。web/db/init/createdatabase.sqlCREATE DATABASE app; USE app; CREATE TABLE users( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), email VARCHAR(255) ); INSERT INTO users(name,email) VALUES('sample','sample@sample.com'); INSERT INTO users(name,email) VALUES('test','test@test.com'); INSERT INTO users(name,email) VALUES('app','app@app.com'); GRANT ALL ON app.* TO test;以上の設定でdocker-composeでMySQLのコンテナを起動します。
$ docker-compose up $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bef9a864276c mysql "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
docker ps
の結果にapp_db
が表示されればコンテナを起動できています。
一度コンテナ内に入って、データベースが作成されているかを確認します。$ docker exec -it app_db bash root@00000000000:/# mysql -u test -p mysql> show databases; +--------------------+ | Database | +--------------------+ | app | | information_schema | +--------------------+ 2 rows in set (0.00 sec) mysql> use app; mysql> select * from users; +----+--------+-------------------+ | id | name | email | +----+--------+-------------------+ | 1 | sample | sample@sample.com | | 2 | test | test@test.com | | 3 | app | app@app.com | +----+--------+-------------------+ 3 rows in set (0.01 sec)
app
というデータベースが作成されていることが確認できます。更に、createdatabase.sql
のテーブルとデータが作成されていることが確認できます。
MySQLの構築は以上です。APコンテナの構築
APサーバーとして
NGINX Unit
を、実行環境にPython3
を、フレームワークとしてFlask
を使用したコンテナを構築します。
NGINX Unitの公式ドキュメントを参考に構築していきます。
イメージはこんな感じです。NGINX Unitのコンテナの起動
まずは、NGINX UnitのイメージからPython3とFlaskの環境を構築します。開発環境の最小単位はこれでいいかもしれません。
web/python
ディレクトリにDockerfile
を追加します。web/python/DorckerfileFROM nginx/unit:1.14.0-python3.7 WORKDIR /usr/src/app COPY src . RUN apt update && apt install -y python3-pip \ && pip3 install --no-cache-dir -r ./requirements.txt \ && rm -rf /var/lib/apt/lists/* CMD ["sleep","infinity"]Docker Hubのnginx/unitのサイトから、NGINX UnitのPython3.7用のイメージを使用します。
次に、
pip
でライブラリを一括でインストールできるように、web/python/src
ディレクトリにrequirements.txt
を作成します。web/python/src/requirements.txtFlask == 1.1.1 flask-sqlalchemy == 2.4.1 PyMySQL == 0.9.3
docker-compose.yml
にNGINX Unitのコンテナの設定を追記します。docker-compose.ymlversion: "3" services: db: image: mysql ports: - "33306:3306" expose: - "3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: test MYSQL_PASSWORD: test volumes: - ./db/init:/docker-entrypoint-initdb.d container_name: app_db # ↓↓追記 ap: build: ./python ports: - "8080:8080" environment: TZ: "Asia/Tokyo" container_name: app_ap depends_on: - db作成した'Dockerfile'は
web/python
のディレクトリに存在するので、buildでその場所を指定します。
サーバーのポートは8080
をホストに公開するようにします。
起動しているDockerコンテナを停止してから、docker-compose build
でビルドしてからコンテナを起動します。$ docker-compose down $ docker-compose build --no-cache $ docker-compose up $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES daf4ddc7c11a web_ap "sleep infinity" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp app_ap 565eb32e6a39 mysql "docker-entrypoint.s…" 43 seconds ago Up 41 seconds 33060/tcp, 0.0.0.0:33306->3306/tcp app_dbMySQLのコンテナの
app_db
と、NGINX Unitのコンテナのapp_ap
が起動していることが確認できます。
NGINX Unitのコンテナに入り、requirements.txt
のライブラリがインストールされているかを確認します。$ docker exec -it app_ap bash root@00000000000:/# python3 -V Python 3.7.3 root@00000000000:/# pip3 freeze Flask==1.1.1 Flask-SQLAlchemy==2.4.1 PyMySQL==0.9.3上記のライブラリ以外にも、
SQLAlchemy
やJinja2
などがインストールされています。
ここまでNGINX Unitのコンテナの起動は完了です。続いて、Flaskの実装を行います。Flaskアプリケーションの実装
Flaskアプリケーションの実装をします。作成するファイルとディレクトリは以下のようになります。
./web |- db | |- init | |- createdatabase.sql |- nginx |- python | |- src | | |- app.py ← 追加 | | |- config.json ← 追加 | | |- config.py ← 追加 | | |- run.py ← 追加 | | |- users.py ← 追加 | | |- requirements.txt | | |- templates ← 追加 | | |- list.html ← 追加 | |- Dockerfile ← 更新 |- docker-compose.yml
各ファイルは以下のように実装します。
config.py
まずは、DBの接続先などの設定クラスを実装する
config.py
です。
ホスト先は、DBコンテナのコンテナ名app_db
で指定します。web/python/src/config.pyclass Config(object): ''' Config Class ''' # DB URL SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://test:test@app_db:3306/app?charset=utf8'app.py
次にFlaskアプリケーションを起動する
app.py
です。
config.from_object()
でアプリケーションの設定クラスを呼び込み、SQLAlchemy()
でFlaskアプリケーションでSQLAchemyが使えるように初期化を行います。web/python/src/app.pyfrom config import Config from flask import Flask from flask_sqlalchemy import SQLAlchemy # Create Flask Application application = Flask(__name__) # Set Config Class application.config.from_object(Config) # Set DB db = SQLAlchemy(application)users.py
次にusersテーブルのModelクラスを作成します。
db.Model
クラスを継承したUsersクラスを作成します。web/python/src/users.pyfrom app import db class Users(db.Model): ''' Users Table Model ''' __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) email = db.Column(db.String(255)) def __init__(self,name,email): self.name = name self.email = emailrun.py
次に、Flaskアプリケーションの起動とルーティングのモジュール
run.py
です。
レスポンスにテンプレートファイルを使用するので、render_template()
でテンプレートファイルとオブジェクトを指定します。web/python/src/run.pyfrom app import application from users import Users from flask import render_template @application.route('/list') def index(): users = Users.query.order_by(Users.id).all() return render_template('list.html', users=users) if __name__ == '__main__': application.run(host='0.0.0.0', port='8080')list.html
次にテンプレートファイルとなる
list.html
を作成します。
render_template()
でusers
オブジェクトが渡されるので、テンプレートエンジンであるJinja2
を使用して実装します。web/python/src/templates/list.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Flask Sample</title> </head> <body> <h1>Flask Sample</h1> <table border="1" style="border-collapse: collapse"> <thead> <tr> <th >Id</th> <th >Name</th> <th >EMail</th> </tr> </thead> <tbody> {% for user in users %} <tr> <td>{{user.id}}</td> <td>{{user.name}}</td> <td>{{user.email}}</td> </tr> {% endfor %} </tbody> </table> </body> </html>Dockerfile
Dockerfile
を更新します。web/python/DorckerfileFROM nginx/unit:1.14.0-python3.7 WORKDIR /usr/src/app COPY src . RUN apt update && apt install -y python3-pip \ && pip3 install --no-cache-dir -r ./requirements.txt \ && rm -rf /var/lib/apt/lists/* # ↓↓削除config.json
最後にNGINX Unitの設定ファイル
config.json
を追加します。web/python/src/config.json{ "listeners": { "*:8080": { "pass": "applications/app" } }, "applications": { "app": { "type": "python", "processes": 2, "path": "/usr/src/app/", "module": "run" } } }実装は以上です。
ビルドしてからコンテナを起動してみましょう。
$ docker-compose down $ docker-compose build --no-cache $ docker-compose up $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES daf4ddc7c11a web_ap "sleep infinity" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp app_ap 565eb32e6a39 mysql "docker-entrypoint.s…" 43 seconds ago Up 41 seconds 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
app_ap
のコンテナの起動後に、コンテナにアクセスしてNGINX Unitの設定ファイルを設定します。$ docker exec -it app_ap bash root@00000000000:/# curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config { "success": "Reconfiguration done." }ブラウザで、
http://localhost:8080/list
にアクセスして画面が表示されます。これでAPコンテナの構築は終了です。
Webコンテナの構築
最後にWEBサーバーのNGINXのコンテナを構築していきます。
これでNGINX <-> NGINX Unit <-> Flask <-> MySQL
の構成になります。追加、更新するファイルは以下のようになります。
./web |- db | |- init | |- createdatabase.sql |- nginx | |- Dockerfile ← 追加 | |- index.html ← 追加 | |- nginx.conf ← 追加 |- python | |- src | | |- __init__.py | | |- app.py | | |- config.json | | |- config.py | | |- run.py | | |- users.py | | |- requirements.txt | | |- templates | | |- index.html | |- Dockerfile |- docker-compose.yml ← 更新まずはトップページとなる
index.html
を作成します。web/nginx/index.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Index</title> </head> <body> <h1>Index</h1> <a href="/list">List</a> </body> </html>次に
NGINX
のDockerfile
を作成します。FROM nginx WORKDIR /var/www/html COPY ./index.html ./ CMD ["nginx", "-g", "daemon off;","-c","/etc/nginx/nginx.conf"]次に、NGINXの設定ファイルを作成します。前回の記事で紹介した設定ファイルから、APサーバーのホストをDocker用に変更します。
nginx.confuser nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; server_tokens off; keepalive_timeout 65; #gzip on; upstream unit-python { server app_ap:8080; # container_nameで指定 } server { listen 80; server_name localhost; # トップページを表示 location / { root /var/www/html; } # /listはAPコンテナにルーティング location /list { proxy_pass http://unit-python; proxy_set_header Host $host; } } }最後にdocker-composeを更新します。
docker-compose.ymlversion: "3" services: db: image: mysql ports: - "33306:3306" expose: - "3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: test MYSQL_PASSWORD: test volumes: - ./db/init:/docker-entrypoint-initdb.d container_name: app_db ap: build: context: ./python args: project_directory: "/src/" # ↓↓更新 expose: - "8080" volumes: - "./python/src:/projects" environment: TZ: "Asia/Tokyo" container_name: app_ap depends_on: - db # ↓↓追加 web: build: ./nginx volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf ports: - "80:80" environment: TZ: "Asia/Tokyo" container_name: "app_web" depends_on: - apビルドしてからコンテナを起動してみましょう。
$ docker-compose down $ docker-compose build --no-cache $ docker-compose up $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5b0f06b89db4 web_web "nginx -g 'daemon of…" 2 minutes ago Up 23 seconds 0.0.0.0:80->80/tcp app_web 625f3c025a82 web_ap "/usr/local/bin/dock…" 2 minutes ago Up 2 minutes 8080/tcp app_ap fe5bf54411a2 mysql "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 33060/tcp, 0.0.0.0:33306->3306/tcp app_dbapp_apのコンテナの起動後に、コンテナにアクセスしてNGINX Unitの設定ファイルを設定します。
$ docker exec -it app_ap bash root@00000000000:/# curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config { "success": "Reconfiguration done." }ブラウザで、
http://localhost:80
にアクセスするとトップページのindex.html
が表示されます。(8080ポートではアクセスできません)リンクとなっている
List
を押下すると、Flaskアプリケーションのlist.html
が表示されます。以上でNGINXの構築は終了です。
まとめ
DockerでNGINX + NGINX Unit + MySQLの環境を構築することができました。
あとはアプリケーションを作り込むだけです。
- 投稿日:2020-03-05T04:14:33+09:00
Docker① Dockerはじめました。
師匠「環境構築にはDockerを使いましょう」
ぼく「承知っす!!!(Docker...?)」
ってことでDockerについて調べてみました。Dockerとは
参考
Docker入門(第一回)~Dockerとは何か、何が良いのか~
要約
Dockerは、コンテナ型の仮想環境を配布・実行するためのプラットフォーム。
仮想マシンとは違う。
- 仮想マシン ホストマシン上でハイパーバイザを利用してゲストOSを動かす。そのうえでミドルウェアなどを動かす。
- Docker ホストマシンのカーネルを利用して、プロセスやユーザを隔離する。従って軽量・高速。
ミドルウェアのインストールや各種環境設定をコード化して管理する。
- コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
- 作成した環境を配布しやすい。
- スクラップ&ビルドが容易にできる。
Dockerイメージは、Web上のDocker Hubで公開されている。
Dockerイメージを取得すれば、すでに必要なミドルウェアなどがインストールされているDockerコンテナを起動できる。感想
仮想マシンより軽快に動くらしい。確かに仮想マシンってもっさりしている印象あるよね。
「コード化して管理」ってなんか今風な感じ。
いまいちイメージわかないけど、とりあえず触ってみよう。Dockerセットアップ、コンテナ起動
参考
Docker入門(第二回)~Dockerセットアップ、コンテナ起動~
Dockerのインストール
ハマった。
例はCentOSだけど、Linuxが好きなのでAmazon Linux2に入れようとした。
いくらやっても
sudo amazon-linux-extras install docker
これでこける。失敗例 # sudo amazon-linux-extras install docker Installing docker Loaded plugins: extras_suggestions, langpacks, priorities, update-motd Cleaning repos: amzn2-core amzn2extra-docker docker-ce-stable 12 metadata files removed 6 sqlite files removed 0 metadata files removed (略) Resolving Dependencies --> Running transaction check ---> Package docker.x86_64 0:18.09.9ce-2.amzn2 will be installed --> Processing Dependency: runc = 1.0.0 for package: docker-18.09.9ce-2.amzn2.x86_64 --> Processing Dependency: containerd = 1.2.6 for package: docker-18.09.9ce-2.amzn2.x86_64 --> Processing Dependency: pigz for package: docker-18.09.9ce-2.amzn2.x86_64 --> Processing Dependency: libcgroup for package: docker-18.09.9ce-2.amzn2.x86_64 --> Running transaction check ---> Package containerd.io.x86_64 0:1.2.13-3.1.el7 will be installed --> Processing Dependency: container-selinux >= 2:2.74 for package: containerd.io-1.2.13-3.1.el7.x86_64 ---> Package libcgroup.x86_64 0:0.41-21.amzn2 will be installed ---> Package pigz.x86_64 0:2.3.4-1.amzn2.0.1 will be installed --> Finished Dependency Resolution Error: Package: containerd.io-1.2.13-3.1.el7.x86_64 (docker-ce-stable) Requires: container-selinux >= 2:2.74 You could try using --skip-broken to work around the problem You could try running: rpm -Va --nofiles --nodigest Installation failed. Check that you have permissions to install.調べてみたら、こんな記事が。
そうかそうか、docker-ce.repoが邪魔だったのね。
なんでCentOSの記事をそのまま引用したんだろう、反省。削除して、もう一回
sudo amazon-linux-extras install docker
でいけました。うんうん、知ってた知ってた。Dockerを動かしてみる
準備
Dockerサービス起動 # systemctl start docker.service サービスの起動確認 # systemctl status docker Dockerの自動起動設定 # systemctl enable docker 試しにDockerコマンド実行 # docker infoこの辺は特に問題なくいきました。
DockerイメージとDockerコンテナ
- まず、Dockerイメージがある。
- Dockerイメージをもとに、Dockerコンテナを起動する。
初期状態
イメージ一覧を表示 # docker images REPOSITORY TAG IMAGE ID CREATED SIZE初期状態では、イメージはない。
従ってヘッダーのみが表示されている。コンテナ一覧を表示 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESコンテナも起動していないため、ヘッダーのみが表示されている。
hello-worldイメージを使ってコンテナを動かす
イメージ取得→起動 # docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/イメージ一覧を表示 # docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 14 months ago 1.84kBイメージが追加されていることを確認。
コンテナ一覧を表示 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24c4702a238c hello-world "/hello" About a minute ago Exited (0) About a minute ago laughing_pascalコンテナも起動していることを確認。
「STAUS」が「Exited」になっているため、正確には停止している。
(hello-worldイメージは、MSGを出漁するだけなので停止で問題ない。)イメージ、コンテナの削除
コンテナ削除 # docker rm <コンテナ名> もしくは # docker rm <CONTAINER ID>イメージ一覧を表示 # docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 14 months ago 1.84kBイメージは消えていない。
コンテナ一覧を表示 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESコンテナは消えている。
イメージ削除 # docker rmi <イメージ名> もしくは # docker rmi <IMAGE ID>イメージ一覧を表示 # docker images REPOSITORY TAG IMAGE ID CREATED SIZEイメージも消えた。
コンテナ一覧を表示 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESもちろん、コンテナは消えている。
Nginxイメージの使用
Nginxイメージの取得 # docker pull nginx Using default tag: latest latest: Pulling from library/nginx 68ced04f60ab: Pull complete c4039fd85dcc: Pull complete c16ce02d3d61: Pull complete Digest: *** Status: Downloaded newer image for nginx:latest Nginxコンテナの起動 # docker run -d --name nginx-container -p 8181:80 nginx起動オプションは以下の通り。
オプション 意味 -d バックグラウンド実行 --name <任意の名前> コンテナ名を指定 -p <ホスト側のPORT>:<コンテナ側のPORT> PORTを指定 http://<サーバのIP>:8181/
で、Nginxにアクセス可能。
(EC2の場合、セキュリティグループの設定変更が必要)Dockerコマンドについて
参考
Docker入門(第三回)~各種dockerコマンドとDockerイメージ作成について~
Docker コマンドチートシート各種コマンドによる操作
- Dockerイメージ取得、イメージ一覧確認
- コンテナ起動、コンテナ一覧確認
- コンテナへのログイン
- ファイルコピー(ホスト→コンテナ内)
- ファイルコピー(コンテナ内→ホスト)
- コンテナからDockerイメージ作成
- コンテナ起動、停止
- コンテナ削除
など。参考のリンク先をみれば良いので割愛。
ホスト側とのディレクトリ共有
起動時にvオプションをつけることで、ホスト側のディレクトリとコンテナ内のディレクトリを共有することが可能。
使用例としては、ログの出力先など。
例えばコンテナ内でログを出力していた場合、コンテナの停止とともに消えてしまうため。
オプション 意味 -v <ホスト側ディレクトリ>:<コンテナ側ディレクトリ> 両ディレクトリを共有にする ディレクトリ共有した状態で起動 # docker run -it -d -p 18080:8080 -v /root/tomcat-container/logs:/share/logs --name tomcat centos:7イメージの作成
ここまではイメージからコンテナを作ってきたが、コンテナからイメージを作ることもできる。
コンテナの停止(やらなくても作成できるみたい。停止したほうが安全?) # docker stop nginx-container nginx-containerコンテナから、nginx2イメージを作成 # docker commit nginx-container nginx_2 イメージを確認 # docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx_2 latest 4a4ce52ad449 6 seconds ago 127MB nginx latest a1523e859360 6 days ago 127MBnginx_2イメージが作成されている。
試しに作成したイメージからコンテナを起動してみる。Nginx_2コンテナの起動 # docker run -d --name nginx2-container -p 8182:80 nginx_2 起動したコンテナの確認 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 53e414bab96d nginx_2 "nginx -g 'daemon of…" 41 seconds ago Up 39 seconds 0.0.0.0:8182->80/tcp nginx2-container 4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 29 minutes 0.0.0.0:8181->80/tcp nginx-container 確認できたので止める # docker stop nginx2-container 停止の確認 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 53e414bab96d nginx_2 "nginx -g 'daemon of…" 2 minutes ago Exited (0) 9 seconds ago nginx2-container 4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 31 minutes 0.0.0.0:8181->80/tcp nginx-container コンテナの削除 # docker rm nginx2-container 削除の確認 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4e29184909ff nginx "nginx -g 'daemon of…" 29 hours ago Up 31 minutes 0.0.0.0:8181->80/tcp nginx-containerDockefileについて
参考
Dockerfileって何?
公開されているDockerイメージに、「必要なパッケージやアプリを追加する」「各種設定をする」など少し手を加えておきたい場合に使用するもの。
Dockerfile内に、実行したい内容を記述する。Dockerfileを使用してみる
…と思ったけど、参考記事の例はtomcatだしちょっと微妙かなと。
どうせならLaravel環境作成したりしたいなと。そんなことを思ってたらこんなものがあった。
Dockerを使ってLaravel開発環境構築
最高っす。ドンピシャっす。
というわけで、実際に動かすのは別の機会にすることにした。コンテナ間通信について
参考
コンテナ間通信
コンテナ同士の通信をするためには、以下2通りの方法がある。
1. Dockerネットワークを作成し、コンテナ名で接続
1. --link オプションを使用して起動するDockerネットワークの作成
例として、Dockerネットワーク(bridgeタイプ)を作成する。
その他のタイプについてはこちら参照とのこと。「network1」というDockerネットワークを作成 # docker network create network1 Dockerネットワークの一覧を表示 # docker network ls NETWORK ID NAME DRIVER SCOPE 064b0ea3a75c bridge bridge local 7281bec71e9e host host local 3585fc587596 network1 bridge local 272c5bc211eb none null local「network1」が存在することが確認できる。
デフォルトで「bridge」も存在しているが、これはDNS設定がされておらず名前解決できないため、コンテナ名を使用したコンテナ間通信ができないらしい。Dockerネットワークの詳細を表示 # docker network inspect network1 [ { "Name": "network1", "Id": "3585fc587596ba17195364d8aea2e77add0978813782bfb21b15486153df109c", "Created": "2020-03-04T17:38:12.168101241Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]「network1」を使用したコンテナを作成 # docker run -d --name nginx3-container --network network1 -p 8183:80 nginx_2 起動したコンテナを確認 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 20158137a4ce nginx_2 "nginx -g 'daemon of…" 3 seconds ago Up 1 second 0.0.0.0:8183->80/tcp nginx3-container 1487009fb41a nginx_2 "nginx -g 'daemon of…" 12 minutes ago Up 12 minutes 0.0.0.0:8182->80/tcp nginx2-container 4e29184909ff nginx "nginx -g 'daemon of…" 35 hours ago Up 6 hours 0.0.0.0:8181->80/tcp nginx-containerなおコンテナ間通信をする場合、PORT番号はコンテナ内部で使用しているPORTを指定すること。
例
MySQLのコンテナを以下のコマンドで作成した場合、ホスト側のPORTは19090、コンテナ内のPORTは9090となる。# docker run --name mysql --network wordpress-network -p 19090:9090 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7この場合、コンテナ間通信で指定するPORTは「9090」となる。
--linkオプションによる通信
あらかじめ、mysqlコンテナを「some-mysql」という名前で作成 # docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7 --linkオプションを用いて「some-mysql:mysql(wordpressコンテナ内で使用しているMySQLのホスト名)」を指定 # docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpressDocker Composeについて
参考
Docker Composeとは
Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。
複数のコンテナを同時に起動したり、オプションを省略できるもの(?)
Docker Composeのインストール
Dockerがインストールされている環境で以下を実行 # curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose Docker Composeのインストールを確認 # docker-compose --version docker-compose version 1.21.2, build a133471docker-compose.ymlについて
Docker Composeを使用する場合、「docker-compose.yml」というファイルが必要となる。
このファイルには、以下のような情報を定義する。
- Dockerイメージをビルドするための情報(使用するDockerfile、イメージ名など)
- コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
- 使用するDockerネットワークmysqlとwordpressのコンテナを起動するrunコマンド
# docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7 # docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpressこれを「docker-compose.yml」に記載すると、以下の通り。
docker-compose.ymlversion: '3' services: wordpress: image: wordpress container_name: some-wordpress restart: always ports: - 8080:80 environment: WORDPRESS_DB_PASSWORD: my-secret-pw mysql: image: mysql:5.7 container_name: some-mysql restart: always environment: MYSQL_ROOT_PASSWORD: my-secret-pw自分で作成した(公開でない)Dockerイメージを使用する場合(例)
docker-compose.ymlversion: '3' services: tomcat: build: ./tomcat image: tomcat-image container_name: tomcat1 ports: - 8081:8080 volumes: - ./tomcat/share/logs:/share/logsrunコマンドのオプションと「docker-compose.yml」の記載内容を比較すると、以下の通り。
設定内容 runコマンドのオプション docker-compose.yml コンテナ名 --name container_name 環境変数 -e environment ポートフォワード -p ports 使用するDockerイメージ コマンドの最後 image Dockerfileの指定 docker buildコマンド build 共有ディレクトリ -v volumes: 「--link」オプションに対応するものはないが、そもそも「docker-compose.yml」を使用した場合は自動でDockerネットワークを作成するため、自動でservice名で名前解決ができるようになっている。
「docker-compose.yml」を使用してコンテナを起動する。
# cd <docker-compose.ymlが置かれているディレクトリ> docker-composeによる起動 # docker-compose up -d 起動の確認 # docker-commpose ps Name Command State Ports ------------------------------------------------------------------------------ some-mysql docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp some-wordpress docker-entrypoint.sh apach ... Up 0.0.0.0:8080->80/tcp次は、Laravel環境を構築をしてみる。
- 投稿日:2020-03-05T00:24:35+09:00
SSHした先のリモートサーバー上のDockerコンテナをVScodeで直接編集する。
概要
リモートワークが提唱される、そんな世の中だから。
開発中に、SSHを使ってリモートサーバーにアクセスすることがある。
さらに、そのリモートサーバーの中でDockerコンテナを作って開発をしたい時、ボリュームをマウントしていればリモートサーバー上のファイルを編集すればコンテナ内のファイルも同時に編集できる。
しかしながら、コンテナをわざわざ立てている時は、プログラムの実行環境がコンテナ内に構築されていることがほとんどのため、このやり方ではデバッグが非常に難しい。以前、VSCodeのRemoteDevelopment をつかって、ローカルのコンテナ内のファイルを直接編集するやり方について記事を書いた(https://qiita.com/kenmaro/items/e23637bdb00d28e1fef6)
が、今回はリモートサーバー上のコンテナ内のファイルをローカルのVSCodeからリモート編集するやり方を解説する。状況説明
リモートサーバはUbuntu想定。リモートサーバ上のコンテナもUbuntu想定です。
1. 自分はPCを使って(家などからリモートで)作業しており、(例えば会社内とかの)サーバーにSSHでログインしたい。
2. そのとき、リモートサーバ上でいつも開発のために使用しているDockerコンテナがある。
3. そのDockerコンテナに直接自分のPCのVSCodeからリモートログインしたい。簡単な流れ
- リモート上のコンテナは、リモートサーバの任意のポートが、コンテナの22番にマッピングされている。
- ssh-keygen を使って、sshするために必要な公開鍵、秘密鍵を作成する。
- 公開鍵を、リモートサーバと、リモートサーバ上のDockerコンテナ上に置く。
- 公開鍵のパーミッションを設定する。
- リモートサーバおよびコンテナ内でssh serverを設定する。
- ローカルPCのSSH configファイルを編集し、リモートサーバおよびコンテナにsshできることを確かめる。
- VSCodeのRemoteDevelopmentを使って、リモートサーバ上のコンテナ内のファイルを、コンテナ内にsshして直接編集できることを確かめる。
という流れになります。めんどくさいように見えますが、流れに従えば多分10分くらいでできます!!
0. リモート上のコンテナは、リモートサーバの任意のポートが、コンテナの22番にマッピングされている。
これは、Docker コンテナをリモートサーバに作る際に、
docker run -p 10000:22
のようにして、リモートのポート(ここでは10000)をコンテナ内の22番ポートにマッピングしときます。1. ssh-keygen を使って、sshするために必要な公開鍵、秘密鍵を作成する。
これに関してはたくさんググれば出てくるので、
https://qiita.com/suthio/items/2760e4cff0e185fe2db9
http://gomocool.net/gomokulog/?p=557
https://webkaru.net/linux/ssh-keygen-command/
などにしたがってローカルPC上に、ssh用の公開鍵と秘密鍵を生成してください。このとき、使う鍵長に気をつけましょう!!2. 公開鍵を、リモートサーバと、リモートサーバ上のDockerコンテナ上に置く。
公開鍵はなんらかの方法でログインしたいリモートサーバ、およびコンテナ内の
~/.ssh/authorized_keys
に保存します。authorized_keys
はファイル名。~/.ssh
というフォルダがない時は、作りましょう。3. 公開鍵のパーミッションを設定する。
リモートサーバ、およびコンテナ内で先ほど作った
~/.ssh/authorized_keys
のパーミッションを設定します。コマンドは、
chmod 600 ~/.ssh/authorized_keys
です。4. リモートサーバおよびコンテナ内でssh serverを設定する。
リモートサーバ、およびコンテナ内で、
apt-get install -y openssh-server
を実行。そのあと、リモートサーバ上で、sshしたいユーザ名(この場合はroot、適宜変更してください。)に応じてsshパスワードを以下のコマンドで決めます。Dockerコンテナで何もユーザー登録していない時は、rootでも良いと思います。
echo 'root:あなたが決めるパスワード' | chpasswd
その後、リモートサーバ上と、コンテナ上で以下のコマンドによりパスワードによるログインを許可。
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
5. ローカルPCのSSH configファイルを編集し、リモートサーバおよびコンテナにsshできることを確かめる。
ローカルPCの、
~/.ssh/config
ファイルを編集します。ない時は作りましょう。以下が例になります。Host myRemoteServer IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes Hostname 192.168.100.20 User username LocalForward 23750 /var/run/docker.sock Host myRemoteDockerContainer IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes HostName 127.0.0.1 User root Port 10000 ProxyCommand ssh -W %h:%p myRemoteServer1つ目の、
myRemoteServer
に関して、
- ssh host は Hostname。
- ssh したいユーザは User。
- IdentityFile は作成した秘密鍵へのパス。(もちろん秘密鍵はローカル側にあるのでローカルのパスです。)2つ目の
myRemoteDockerContainer
に関して、基本的に同じですが、
ProxyCommand ssh -W %h:%p myRemoteServer
により、myRemoteServer
のポート10000
にアクセスという意味。0での手順により、これはコンテナ内の22番ポートにマッピングされる、すなわちコンテナ内にSSHアクセスできる。ここで、ローカルPCのターミナルから、
ssh myRemoteServer
`とすると リモートサーバに無事ログインでき、
ssh myRemoteDockerContainer
とすると リモートサーバ上のコンテナに無事ログインできることを確かめてください。
6. VSCodeのRemoteDevelopmentを使って、リモートサーバ上のコンテナ内のファイルを、コンテナ内にsshして直接編集できることを確かめる。
ここまでくればもうできたも同然です。ローカルPCでVSCodeを開き、エクステンションの
Remote Development
をインストールします。
インストールすると、ウィンドウの一番左下に、緑のボタンができるので、クリック。
そして、
Remote-SSH: Connect to Host
をクリック。
さらに、さきほどconfigファイルに書いた、
myRemoteDockerContainer
を選択し、
echo 'root:あなたが決めるパスワード' | chpasswd
でコンテナサイドで設定したパスワードを入力すると、、、、、無事、VSCodeからリモート内のコンテナに直接アクセスできるはずです。
まとめ
すばらしい、マイクロソフト先生すばらしい、、、!!!
おわり