こんにちは、奥村です。
今回のエンジニアブログも前回に引き続き「新卒に捧ぐ!俺の〇〇」シリーズです (前回の記事はこちら↓)
第三回のテーマはタイトルの通り
「新卒に捧ぐ!俺の開発環境」
です。
新人エンジニアにとって開発環境を準備するのは、どんな環境を用意したら良いのか悩んでしまうことが多いですよね。
本記事では2人のエンジニアがどのような環境で開発しているかを紹介しています。 是非参考にしてみてください。
- 一人目:メインでscala、たまにHTML,javascriptを扱っている(古川)
- 二人目:ruby on Railsで開発を行なうことがメイン(足立)
一人目
こんにちは、古川です。PCはMacbook Proをつかっています。
入社して以来色々な言語をさわってきましたが、最近はScala、たまにHTMLやJavascriptを使ってサービスを開発しています。
■ エディター
- Scalaの開発の場合
他の言語はいくつか選択肢あると思いますが、Scalaに至ってはIntelliJ IDEA一択かと感じています。
なぜなら、補完機能やリファクタリング機能・デバッグ機能などが充実しているからです。
IntelliJ IDEAにはCommunity版とUltimate版がありますが、Scalaメインの開発だけならCommunity版でも十分です。HTMLなどの開発もやりたいのならUltimate版にしたほうが良さそうです。
自分の場合は、WebAPIの開発が多く、HTMLなどを扱うことはそこまで多くないので、Community版で事足りてます。
また、必要に応じてプラグインを入れればDockerやShellスクリプトにも対応してくれるので個人的に便利だと思います。
- HTMLやJavascriptの開発の場合
こちらは選択肢はたくさんありますが、個人的にはVisual Studio Codeがオススメでしょう。
Javascriptの場合は簡単にデバッグ実行ができますし、コードジャンプやリファクタリング機能も使えるので重宝しています。
■ 開発環境の整備
サービス開発をする際、MySQLやRedisなどミドルウェアを用意しておく必要があったので、かつては「仮想マシンを作り、ミドルウェアと必要なライブラリをインストール」そして他人に渡す場合は、「それをコピーする」なんてことをしていました。
しかし、つぎの問題があって開発がはばかられます。
- 仮想マシン自体を立ち上げるとPCが重くなっていく
- 特に複数プロジェクトに関わっていたときは、その分仮想マシンを立ち上げておかないといけなく、そのせいでCPUやメモリを食い尽くすわで、本当に大変でした
- 仮想マシンをコピーしたとき、オレオレ設定を相手に強要させてしまうことはまだしも、下手すると必要以上の情報が他人に渡ってしまうこともある
- 仮想マシンを使えば使うほど容量が大きくなるので、HDDを圧迫させてしまうだけでなく、他人に渡すのも時間がかかって大変
- 仮想マシンの起動に時間がかかるのですぐに開発に取り掛かれない
- Sambaなどのツールでホストとつなげておかないと、好きな開発環境で開発ができない
そこで最近はDockerを使って、サービス単位でミドルウェアの管理しています。
Dockerを使うことでコレくらいのメリットはあるので、開発環境の整備にはうってつけです。
- ミドルウェアが必要になったときはコンテナを立ち上げたり落としたりすれば良くなるので、マシン環境を汚すことなくミドルウェアが簡単に扱える
- 仮想マシンは立ち上げに数十秒以上はかかるものの、コンテナは立ち上がる速度もたったの数秒
さらにDocker Composeを使えば、プロジェクトごとに必要なミドルウェアをコードで設定できるので環境整備がかなり楽になるだけでなく、開発環境の切り替えも楽になります。
具体的には、サービスのプロジェクトごとにこんな感じにdocker-compose.yml
を定義しておき、
version: '2' services: db: image: mysql:5.7 environment: MYSQL_DATABASE: eventapi MYSQL_USER: admin MYSQL_PASSWORD: secret MYSQL_ROOT_PASSWORD: password ports: - "3306:3306"
開発時には、このコマンドをうてばサービスに必要なミドルウェアは一発で立ち上がります。
docker-compose up -d
そして、違うプロジェクトの開発をしたい場合は、このコマンドでコンテナを落としておき、違うプロジェクトで同じようにコンテナを立ち上げるだけで良いです。
docker-compose down
なので、プロジェクトの切り替えに時間をあまりかかりません。
また、大体のミドルウェアはDocker Hubに公開されていますので、環境構築自体も時間はかかりません。
もし存在しないバージョンのミドルウェアやサービス専用のコンテナを作りたい場合は、(用意するまでは大変なものの)Dockerfileでコンテナイメージを作っておき、一度公開さえしておけば、他の人もすぐにそのコンテナイメージを利用できるようになります。
ただし、うちの場合は社外に公開したくないコンテナイメージもあるので、その場合は社内に立ててあるGitLabのリポジトリにアップロードしています。
■ その他
Macbook Proは熱くなると極端に重くなります。重くなると本当に仕事にならなくなるので、冷却台を使っています。
自分はこの冷却台を使っています。
冷却台を買う前は、ちょっと重いプロセスを走らせるとすぐカクカクになってしまいましたが、この冷却台をつかっているときは重くなることはだいぶ減りました。
冷却台は正直なんでも良いと思いますが、評判の高そうなものを選んだほうがいいと思います。
二人目
初めまして。社会人2年目エンジニアの足立です。
最近、開発環境をDocker Composeを使って構築するように変更して便利だったので紹介します。 便利な点としては
- 誰でも同じ環境を作れる
- テスト環境と同じ環境を準備できる
- ローカル環境でのミドルウェアの管理が便利
- 設定さえしっかりすれば、コマンド2つで開発環境が立ち上がる
等が挙げられます。
以下では、デモを通して、この便利な開発環境を手に入れる方法を紹介していきます。
デモのゴール
- railsでresqueを使用し、workerでjobを回しlogに「HelloWorld」を出力されていることを確認する。
使用環境
Docker for Mac(version 17.03.1-ce-mac5)
docker-compose(version 1.11.2)
■ docker-compose関係のファイル
下記のコンテナを用意するため、
- Dockerfile
- Dockerfile-nginx
- docker-compose.yml
を作成します
〜railsのプロジェクトは用意している前提で話をさせて頂きます。〜
コンテナ | 詳細 |
---|---|
datastore | 永続化、共有したいパス設定 |
redis | redisサーバー |
nginx | nginxサーバー |
rails | railsサーバー |
・Dockerfile
RUN apt-get update && apt-get install -y vim locales --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN dpkg-reconfigure locales && \ locale-gen C.UTF-8 && \ /usr/sbin/update-locale LANG=C.UTF-8 ENV LC_ALL C.UTF-8 ENV TERM xterm # END: ~~~~~ 日本語対応 RUN mkdir -p /usr/src/docker_compose_app RUN mkdir -p /usr/src/docker_compose_app/tmp WORKDIR /usr/src/docker_compose_app COPY ./Gemfile /usr/src/docker_compose_app/Gemfile COPY ./Gemfile.lock /usr/src/docker_compose_app/Gemfile.lock RUN bundle install -j4 EXPOSE 3000 ENV RUN_AT_EXIT_HOOKS=1 ENV VERBOSE=1 ENV PIDFILE=./tmp/resque.pid ENV TERM_CHILD=1 ENV QUEUE='resque_sample' CMD bash -c "bundle exec unicorn_rails -c config/unicorn/docker.rb -E docker -D && bundle exec rake resque:work"
DockerfileでCMDが一つしか使えないのを知らなくて少し詰まりました。。
・Dockerfile-nginx
FROM nginx:1.11.0-alpine # Docker Hubからimageを持ってきます COPY container/nginx/vh-site.conf /etc/nginx/conf.d/default.conf EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"]
・docker-compose.yml
--- version: '2' services: datastore: build: container/datastore container_name: docker-test-container redis: image: redis:3.2.0 # Docker Hubからimageを持ってきます ports: - '6379:6379' nginx: build: context: . dockerfile: Dockerfile-nginx ports: - '8080:80' links: - rails volumes: - .:/usr/src/docker_compose_app - ./tmp/logs/:/var/log/nginx # ここでコンテナ内のlogをローカルの/tmp/logs以下にマウント volumes_from: - datastore rails: build: . ports: - '3000:3000' links: - redis environment: RAILS_ENV: docker volumes: - .:/usr/src/docker_compose_app volumes_from: - datastore
・container/datastore/Dockerfile
FROM busybox:latest VOLUME /usr/src/app/tmp VOLUME /usr/src/app/public/system CMD /bin/sh
・container/nginx/vh-site.conf
upstream docker_compose_app { server rails:3000 fail_timeout=0; } server { listen 80; server_name localhost; root /usr/src/docker_compose_app/public; location / { try_files $uri @webapp; } location @webapp { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://docker_compose_app; } location ~ ^/(assets|uploads)/ { gzip_static on; gzip_types text/css text/js text/xml; add_header Cache-Control public; break; } error_page 404 /40x.html; location = /40x.html { index 404.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
Dockerfileのオプションの詳細は過去の記事に纏めてあるので下記を参照してください。
Docker Composeを使ってマイクロサービスを作ってみた
■ ファイルの削除・ファイル設定
今回はデータベースは使わないので不要ファイルは削除します
rm config/database.yml
config/application.rb
のファイルの require 'rails/all'
をコメントアウトし下記を追加し、
config.active_record.raise_in_transactional_callbacks = true
こいつもコメントアウトします。
# config/application.rb # require 'rails/all' require 'action_controller/railtie' require 'action_mailer/railtie' require 'sprockets/railtie' require 'rails/test_unit/railtie' module DockerComposeApp class Application < Rails::Application # config.active_record.raise_in_transactional_callbacks = true end end
config/environments/docker.rb
の config.assets.debug = false
に変更します。
# config/environments/docker.rb config.assets.debug = false # falseに変更
・Resqueの設定
mkdir workers vim workers/hello.rb
class Hello @queue = :resque_sample def self.perform(msg) sleep 5 logger = Logger.new(File.join(Rails.root, 'log', 'resque.log')) logger.info "HelloWorld!! [#{msg}]" end end
・Rakeタスクを追加
lib/tasks/resque.rake
require 'resque/tasks' task "resque:setup" => :environment
resqueの設定
config/initializers/resque.rb
require 'resque' Resque.redis = 'redis:6379' # 環境に合わせて変更必要あり(docker環境のみならOK)
・Railsのルーティング設定
config/routes.rb
require 'resque_web' Rails.application.routes.draw do mount ResqueWeb::Engine => "/" get '/resque_web' => redirect('/') end
■ 開発環境の起動
docker-compose build
← このコマンドでimage作成
docker-compose up -d
← このコマンドでimageを使ってコンテナ作成 + 起動
docker ps
← 起動中のコンテナの確認
docker-compose build docker-compose up -d docker ps
上記の画像のようにコンテナ
- nginx
- rails
- redis
のコンテナ3台が立ち上がれば成功です。
今のままだとprecompileが通ってないので下記のコマンドを叩いてprecompileを行いrails再起動します。
docker-compose run rails rake assets:precompile && docker-compose restart rails
これで localhost:8080
にアクセスするとResqueのページが無事に表示されるかと思います。
これでようやく準備ができました。
コマンドラインでjobを生成してredis::workerが動くか確認していきましょう。
#jobの生成 docker-compose run rails bundle exec rails runner 'Resque.enqueue(Hello, "hogeee")'[f:id:AdwaysEngineerBlog:20170419114708p:plain]
動いていますね!
ログを見てみましょう
tail -f log/resque.log
しっかりと「HelloWorld!!」が表示されていますね!
ハマりポイント
Already running on PID:14 (or pid=/usr/src/docker_compose_app/tmp/unicorn.pid is stale) (ArgumentError)
このエラーを初めてみたときは、コンテナ立ってないんだから入れなくない??っとパニクりましたが先輩に聞いて解決しました。
上記のエラーが出たら
#コンテナの中に入る docker-compose run コンテナ名(rails) bash # ゴミファイルを削除する rm tmp/unicorn.pid # railsコンテナを起動させる docker-compose start rails
まとめ
新しくチームにジョインする人も簡単に開発環境を手に入れられるのがdocker-composeの強みだなと感じています。
( dockerコマンドの学習コストはありますが。。
以上です。ありがとうございました。
以上になります。今の内から開発環境にこだわっておくとあとあと楽になると思います。
色々試して自分が使いやすいものを選択できるようになると良いですね!