はじめに
最近、と言ってもこのアプリを作ったのは2021年終わりから2022年前半くらいになるのですが、
未経験エンジニアのポートフォリオのレベルがだいぶ上がっているという話を耳にすることが多く、未経験で業界に飛び込んだ自分も負けていられないなという思いから業務後にコツコツアプリを作ってみました。
先に言い訳をしておくと、転職活動中だったこともありTerraform
でインフラのコード化までやり切ることができず、テストコードも未実装というかなりお粗末なアプリになってしまいました。反省。。。
ただ、業務と並行して未経験の技術をキャッチアップしていたことが転職面接時には結構ウケが良かったので、ある程度プラス評価はしてもらったかなと思っています。
あとシンプルに自分の作りたいものが形になっていくのはやっぱり楽しいですね!
話を戻すと、当時は実務で使用したことのなかった技術が多かったこともありかなり手探りで実装しました。
この記事では、そのときに参考にした学習教材やブログなどをまとめてみました。
だいぶ色々なサイトを巡回したこともあり、おそらく記載漏れがあるので適宜更新したいと思います。
アプリ概要
ファッションが好きなこともあり、セレクトショップや古着屋に行くことが多かったのですが、毎回インスタやGoogleマップで場所を調べるのにうんざりしていたので、こうしたショップをまとめた「食べログ」みたいなサイトがあれば便利かなと思って作ってみました。
懺悔するとフロント側は完全に某マッチングアプリの画面をパ○りました。
メインはバックエンド側とインフラ側だったのでご勘弁を............
開発環境
・Vue.js 3.2.31
・Ruby 2.6.6
・Ruby on Rails 6.0.4.6
・MySQL 5.6
・Docker 20.10.7
・Circle Ci 2.1
ディレクトリ構成
shop
┣ .circleci
┣ frontend (Vueアプリケーションを配置)
┗ shop_api (Railsアプリケーションを配置)
Dockerfile
# shop/frontend/Dockerfile
FROM node:12.18.3-alpine
ENV APP_HOME /app
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
RUN apk update && \
npm install -g @vue/cli && \
npm install --save axios
# shop/shop_api/Dockerfile.development
FROM ruby:2.6.6
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir /app
ENV APP_ROOT /app
WORKDIR $APP_ROOT
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock
RUN gem install bundler:2.3.6 && \
bundle install
# shop/shop_api/Dockerfile.production
FROM ruby:2.6.6
ENV RAILS_ENV=production
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
RUN mkdir /app
WORKDIR /app
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
sudo \
nginx && \
gem install bundler:2.0.1
RUN bundle install
ADD . /app
RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids
# nginx
RUN groupadd nginx
RUN useradd -g nginx nginx
ADD nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
RUN chmod +x /app/entrypoint.sh
CMD ["/app/entrypoint.sh"]
## shop/docker-compose.yml
version: "3"
services:
db:
container_name: db
image: mysql:5.7.30
environment:
TZ: Asia/Tokyo
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_ROOT_PASSWORD: password
volumes:
- mysql_data:/var/lib/mysql
ports:
- 3307:3306
networks:
app_net:
ipv4_address: '172.20.0.2'
frontend:
container_name: frontend
image: frontend
build: ./frontend
volumes:
- ./frontend:/app
ports:
- '8080:8080'
tty: true
stdin_open: true
command: npm run serve
shop_api:
container_name: shop_api_development
build:
context: ./shop_api/
dockerfile: Dockerfile.development
image: shop_api_development
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails server -b 0.0.0.0"
tty: true
stdin_open: true
volumes:
- ./shop_api:/app:cached
- bundle_data:/usr/local/bundle:cached
- /app/vendor
- /app/tmp
- /app/log
- /app/.git
environment:
TZ: Asia/Tokyo
depends_on:
- db
ports:
- 3000:3000
networks:
app_net:
ipv4_address: '172.20.0.3'
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/24
volumes:
mysql_data:
bundle_data:
CircleCi
# shop/.circleci/config.yml
version: 2.1
jobs:
shop_api:
docker:
- image: circleci/ruby:2.6.6-stretch-node
environment:
RAILS_ENV: test
DB_HOST: 127.0.0.1
- image: circleci/mysql:5.7.30
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_ROOT_PASSWORD: password
working_directory: ~/repo
steps:
- checkout
# restore gem from cache
- restore_cache:
keys:
- gem-cache-v1-{{ checksum "~/repo/shop_api/Gemfile.lock" }}
- gem-cache-v1-
working_directory: ~/repo/shop_api
# gem install
- run:
command: |
gem install bundler
bundle config set path 'vendor/bundle'
bundle install --jobs=4 --retry=3
working_directory: ~/repo/shop_api
- save_cache:
key: gem-cache-v1-{{ checksum "~/repo/shop_api/Gemfile.lock" }}
paths:
- ~/repo/shop_api/vendor/bundle
working_directory: ~/repo/shop_api
# Database setup
- run:
command: bundle exec rails db:create
working_directory: ~/repo/shop_api
- run:
command: bundle exec rails db:migrate
working_directory: ~/repo/shop_api
- run:
name: create directory to store test results
command: mkdir /tmp/test-results
working_directory: ~/repo/shop_api
# run tests
- run:
name: RSpec
command: |
bundle exec rspec $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) \
|| (printf "====== RETRYING...\n\n\n"; bundle exec rspec --only-failures)
working_directory: ~/repo/shop_api
# collect reports
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
- store_artifacts:
path: /home/circleci/repo/tmp/screenshots
frontend:
docker:
- image: circleci/node:14.3
environment:
NODE_ENV: test
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "~/repo/frontend/package.json" }}
working_directory: ~/repo/frontend
- run:
name: install-packages
command: npm install
working_directory: ~/repo/frontend
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "~/repo/frontend/package.json" }}
working_directory: ~/repo/frontend
- run:
name: test
command: npm run test
working_directory: ~/repo/frontend
workflows:
version: 2
test:
jobs:
- shop_api:
filters:
branches:
ignore: main
- frontend:
filters:
branches:
ignore: main
インフラ構成図
参考にした教材、記事
Ruby
Rubyを学ぶにはやはりこれ
ボリュームはありますが、わかりやすい説明でスッと理解しやすい技術書でした。
Qiitaにも学習後のアウトプットを投稿している人も多くいるので、振り返りでサクッと読み返したりするのも効果的かなと思います。
RSpec
著者の伊藤さんはQiitaなどでRSpecやRubyやRailsでリファクタリングに使えるメソッドやコードの書き方などを体系的に投稿しているので、こちらもかなり勉強になる内容でした。
RSpecはdescribe
やcontext
の関係、マッチャなどの聞きなれない用語もそうですが、let
の遅延評価など独特な構文を持っているため最初は???となることが多く、苦手意識を持ちやすいので、ここで基礎を固めてしまうのが良いと思います。
Qiitaは書籍と異なり体系的に技術を学ぶことは難しいですが、この記事では入門から応用までパート別で解説をしており、初学者でも学びやすい内容だと思います。
自分がRSpecを書くときに一番役に立ちました!
と言いつつポートフォリオではテストコードを書いてない矛盾…………………
その後、実務でキャッチアップしたので許してほしい……………..(まあまあ苦労した)
Rails APIモード
Rails APIモードに関しては、こちらでサクッと勉強してみた覚えがあります。
Postman
を使用して、APIのテストなんかもやっていました。
Swagger
とか導入できたらWeb上でサクサクAPIいじれたのかなと思う今日この頃。
それかもっとモダンな技術があるかも.........
Vue.js
Vue.jsの基礎を学習するのに利用しました。
説明も丁寧でわかりやすく、基礎を固める上でかなり有効な教材でした。
Qiitaで学習するのも結構好きなんですが、やっぱり体系的に学習しとくと安心感?があります。
AWS
VPC、サブネットなどの基礎
こちらの記事では割と初期のVPCやサブネットの作成などを参考にしました。
どうしても忘れている箇所が多かったので非常に助かりました。
後編もあるのでそちらも参考にしました。こういう丁寧な記事が書ける人は本当すごい....
Route53, RDS, ECSなど
Next + Ruby on Railsの記事ですが、Circle CIの導入からAWS Route53、RDS、ECS、SSLの設定など大いに参考にさせていただきました。
フロント側、バックエンド側のDockerfileについてもコードが記載されていたので、こちらを参考にカスタマイズしながら開発環境を構築した覚えがあります。
S3(静的ウェブサイトホスティング), CloudFrontなど
S3の静的ウェブサイトホスティングにVueのフロント側を配置したのですが、独自ドメイン取得やCloudFrontの設定など参考にさせていただきました。
存在は知っていたのですが、こんなに簡単にページを公開できるかと感動した覚えがあります。
デプロイ用のコマンドの作り方まで記載していたので、もう少し自分もできることがあったなあと…
最後に
記事を書くまでにだいぶ期間が空いてしまいましたが、これから同じような技術スタックでアプリを作ろうする人の参考になればと嬉しいです。
ただ当時自分は中途半端に実務経験があったこともあり、完全未経験ではないので初学者が網羅的に学ぶ場合には、あまり役に立たない記事だったかもしれません。
また未経験の方のポートフォリオレベルがさらにハイレベルになっていて参考にならなかったら申し訳ないです。
自分の「こんなことやったよ!」「ちょっとだけ褒めて!」っていう範囲を抜け出せていないと思います。
ご了承ください……………
お粗末なアプリということは否定しませんが、業務と並行してある程度形になったアプリ作ったということはインプット、アウトプットに関して自信に繋がったと思います。
業務でも初めて触れる技術でも臆せずよりチャレンジできるようになれたと思います。
何よりインプットだけでは学習にはなっていないということを再度認識できたのが大きかったです。
インプットというコンフォートゾーンから脱出することの大切さ……!!
これから実務ではNuxtやGoも触れていくので勉強していかないとなと
最後まで読んでくださりありがとうございました。