Casual Developers Note

エンジニアやデザイナー向けの技術情報・英語学習情報・海外留学情報・海外旅行情報を提供中。世界を旅して人生を楽しもう。

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • お問い合わせ
現在の場所:ホーム / アーカイブ技術 Tips & Tutorials

2019年10月21日 By KD コメントを書く

BashからZshに移行する方法(Mac編)

BashからZshに移行する方法(Mac編)

MacのOSがmacOS Catalinaになるにあたり、標準のシェルがZshになったので、今まで使っていたBashからZshに移行する方法を紹介します。

はじめに

Macのバーションをアップデートしてシェルを起動すると以下のメッセージが表示されます。

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

これはOSが「macOS Catalina」になるにあたり、標準のシェルがBashからZshに変更されたためです。詳細は公式のページに書かれているのですが、この期にBashからZshに移行することにしましょう。

それでは、BashからZshに移行していきましょう!

方針

今回はBashで個人の設定(「.bashrc」や「.bash_profile」)が終わっている前提で、その設定を壊さないようにしつつ、Zshの基本設定を行うことにします。

Zshの基本設定は、Zshのパッケージマネージャーである「zplug」をまず入れ、それからZshのフレームワークである「Prezto」を入れる方針とします。

もちろん「Homebrew」は設定済みですよね。

BashからZshへ移行

移行していきましょう。

Zshを確認する

まずは、MacにZshがインストール済みであることを確認します。

$ which zsh
/bin/zsh
$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

OKですね。

zplugおよびPreztoをインストールする

Homebrewでzplugをインストールし、Preztoをインストールします。テーマは「Dracula」にします。

なお、今回はBashからZshに移行するので問題ないと思いますが、Preztoをインストールすると「.zlogin」「.zlogout」「.zprofile」「.zshenv」「.zshrc」にシンボリックリンクが張られるので、必要であれば事前に対象ファイルを退避しておきましょう。

$ zsh
$ brew install zplug
$ vi ~/.zshrc
# Initialize zplug via brew
export ZPLUG_HOME=/usr/local/opt/zplug
source $ZPLUG_HOME/init.zsh

# Load configuration framework
zplug "sorin-ionescu/prezto"

# Load pachages
zplug "zsh-users/zsh-completions"
zplug "zsh-users/zsh-autosuggestions"
zplug "zsh-users/zsh-syntax-highlighting"
zplug "zsh-users/zsh-history-substring-search"

# Load theme file
zplug 'dracula/zsh', as:theme

# Install plugins if there are plugins that have not been installed
if ! zplug check --verbose; then
    printf "Install? [y/N]: "
    if read -q; then
        echo; zplug install
    fi
fi

# Source plugins and add commands to $PATH
zplug load --verbose

# Source Prezto.
if [[ -s "${ZDOTDIR:-$HOME}/.zprezto/init.zsh" ]]; then
  source "${ZDOTDIR:-$HOME}/.zprezto/init.zsh"
fi

# Customize to your needs...
$ zplug install
$ ln -s $ZPLUG_HOME/repos/sorin-ionescu/prezto $HOME/.zprezto
$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

Bashの設定をZshの設定に移行する

「.bash_profile」と「.zprofile」、「.bashrc」と「.zshrc」が対応しているので、内容をコピーします。

$ cat ~/.bash_profile >> ~/.zprofile
$ cat ~/.bashrc >> ~/.zshrc

後は、「.zprofile」および「.zshrc」の中身で動いていないところを修正すればOKです。私が修正したところは「おまけ」を参照して下さい。

シェルをZshに変更する

BashからZshに変更します。

$ chsh -s $(which zsh)

これで移行は完了です。

おまけ

Bashの設定をZshの設定に移行する際に修正した箇所

私の場合は以下の3箇所の修正が必要でした。

1. Bashの補完をZshの補完に変更する

「bash-completion」の設定を削除します。代わりに「zsh-completions」を使うのですが、zplugでインストール済です。

2. プロンプトの設定を変更する

「export PS1=…」のように書いていたら削除します。今回はテーマを「Dracula」にしているので、プロンプトの追加の設定はいりません。

もし自前でプロンプトの設定をしたければ、例えば、公式のGitの「ZshでGitを使う」を参考にして、以下のようにすると、Gitのブランチや状態を好きなように表示させることができます。

export PS1="%10F%m%f:%11F%1~%f $ "
autoload -Uz vcs_info
precmd_vcs_info() { vcs_info }
precmd_functions+=( precmd_vcs_info )
setopt prompt_subst
RPROMPT="$vcs_info_msg_0_"
zstyle ':vcs_info:git:*' check-for-changes true
zstyle ':vcs_info:git:*' stagedstr "%F{yellow}!"
zstyle ':vcs_info:git:*' unstagedstr "%F{red}+"
zstyle ':vcs_info:*' formats "%F{green}%c%u[%b]%f"
zstyle ':vcs_info:*' actionformats '[%b|%a]'

3. anyenvの設定を変更する

私は複数のプログラミング言語を書く関係で「anyenv」を使っているので、その設定を以下のように変更します。

$ vi ~/.zshrc
...
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init - zsh)"
...

なお、もし「ndenv」を使っている人は、非推奨になったので、「nodenv」に移行しておきましょう。そうしないと「anyenv」のインストールでエラーになる場合があります。(実際fishを試した際にエラーが出ました)

ついでに、「nodenv」の「default-packages」というプラグインが使いやすいので紹介します。anyenv経由でnodenvをインストールした場合は最初から使えます。これを使えば、新しいnodeをインストールするたびに、予め「default-packages」上に指定しておいたモジュールをグローバルにインストールしてくれます。

$ touch $(nodenv root)/default-packages
$ vi $(nodenv root)/default-packages
yarn
nodemon
jest
eslint
tslint
flow-bin
typescript
@babel/core
@babel/cli
webpack-cli
@webpack-cli/init
parcel-bundler
express-generator
create-react-app
@vue/cli
$ nodenv default-packages install --all

便利ですね。

Zsh変更時のエラー対応

Zsh変更時に以下のエラーが出た場合。

「zsh compinit: insecure directories, run compaudit for list.」

対象フォルダの権限を変更することで対応します。

$ compaudit
There are insecure directories:
/usr/local/share
$ chmod -R 755 /usr/local/share
$ compaudit

ZshからFishに移行する方法

Fishとは、「The friendly interactive shell」の事であり、使いやすいと評判のシェルです。しかし、POSIX非互換のため、設定の書き方が大幅に異なります。そのため、BashからZshに移行するのとは異なり、ZshからFishに移行するのはいろいろ書き直しが必要になります。興味がある方は、ざっくり概要をまとめるので、試してみると良いでしょう。

Fishをインストールする

$ brew install fish
$ which fish
/usr/local/bin/fish
$ echo /usr/local/bin/fish | sudo tee -a /etc/shells
Password:
$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/fish

fisherをインストールする

fisherはFish用のパッケージマネージャーです。

$ fish
$ curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish

パッケージを入れる

適当にパッケージを入れてみます。(好きなパッケージを入れて下さい)

$ fisher add jethrokuan/z
$ fisher add jethrokuan/fzf
$ fisher add oh-my-fish/plugin-peco
$ fisher add decors/fish-ghq
$ fisher add 0rax/fish-bd
$ fisher add edc/bass
$ fisher add oh-my-fish/theme-bobthefish

Zshの設定をFishの設定に移行する

「.zshrc」の内容を「config.fish」にコピーします。

$ cp ~/.zshrc ~/.config/fish/config.fish

後は、地道に以下の修正を行います。

  • zshやzplugの設定を削除する
  • 環境変数を「export PATH=」のような書き方から「set -x PATH」のような書き方に変換する
  • 関数をZshの書き方からFishの書き方に変換する
  • 「anyenv」の読み込みを以下のように修正する (この書き方は頻繁に変わっているので、動かなかった場合は、デフォルトのシェルをFishにした状態で「anyenv init」を実行すれば、その時のanyenvの設定が表示されます)
$ vi ~/.config/fish/config.fish
...
set -x PATH $HOME/.anyenv/bin $PATH
status --is-interactive; and source (anyenv init -|psub)
...

Fishの設定をする

$ fish_config

シェルをFishに変更する

$ chsh -s (which fish)

最後に

いかがでしたか?これで、BashからZshに移行できたことでしょう。後はZshのカスタマイズをすることで、自分色に染めていくと良いでしょう。それでは。

環境

  • PC: macOS Catalina 10.15
  • Homebrew: 2.1.15
  • bash: 3.2.57
  • zsh: 5.7.1
  • zplug: 2.4.2
  • fish: 3.0.2
  • fisher: 3.2.9

カテゴリ : 技術 Tips & Tutorials タグ : bash, mac, prezto, zplug, zsh

2019年9月30日 By KD コメントを書く

Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

create-react-appを使わないでReactの開発環境を構築する方法を紹介します。

はじめに

近年のJavaScriptフレームワークはCLIを使ってワン・コマンドで設定できるようになっています。Reactではそのためのコマンドとしてcreate-react-appが提供されています。creat-react-appは簡単にReactを設定できる反面、設定が隠蔽されてしまい、細かい設定をするためにはejectする羽目になります。しかし、ejectをしてしまえば最後、create-react-appがアップデートされてもアップデートできなくなってしまいます。では、プロダクションなどで設定を細かく設定して管理したい場合はどうすればよいでしょうか?そういう人は自分でゼロから設定しましょう。

ということで、今回はcreate-react-appを使わないで、Reactの開発環境を構築していきましょう。

Reactの開発環境の構築方法

それでは、Reactの設定をしましょう。

前提

以下の設定が完了している必要があります。

  • NodeJSがインストールされていること
  • Yarnがインストールされていること
  • Dockerがインストールしていること

詳しくは、「環境」を参照して下さい。

ベースの作成とパッケージのインストール

必要なフォルダおよびファイルを作成し、必要なパッケージをインストールします。

$ mkdir my-react-app
$ cd my-react-app/
$ yarn init -y
$ mkdir public src
$ touch public/index.html
$ touch src/index.js src/index.css
$ touch src/App.js src/App.test.js src/App.css
$ touch .babelrc webpack.config.babel.js
$ touch jest.config.js
$ mkdir __mocks__
$ touch __mocks__/styleMock.js
$ touch __mocks__/fileMock.js
$ yarn add --dev flow-bin flow-typed
$ yarn flow init
$ tree -aI node_modules
.
├── .babelrc
├── .flowconfig
├── __mocks__
│   ├── fileMock.js
│   └── styleMock.js
├── build
├── jest.config.js
├── package.json
├── public
│   └── index.html
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   └── index.js
├── webpack.config.babel.js
└── yarn.lock
$ yarn add react react-dom
$ yarn add --dev jest jest-enzyme enzyme enzyme-adapter-react-16
$ yarn add --dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-flow @babel/register babel-jest
$ yarn add --dev webpack webpack-cli webpack-dev-server
$ yarn add --dev html-webpack-plugin mini-css-extract-plugin uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin clean-webpack-plugin
$ yarn add --dev babel-loader css-loader html-loader
$ vi package.json
...
  "scripts": {
    "start": "webpack-dev-server --open --mode development",
    "build": "webpack --mode production",
    "test": "jest"
  }
...

準備ができました。

設定を書く

それでは、ファイルの中身を書いていきましょう。

.babelrc

{
  "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-flow"]
}

jest.config.js

module.exports = {
  moduleNameMapper: {
    '\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      '/__mocks__/fileMock.js',
    '\.(css|less)$': '/__mocks__/styleMock.js',
  },
};

__mocks__/styleMock.js

module.exports = {};

__mocks__/fileMock.js

module.exports = 'test-file-stub';

.flowconfig

[ignore]
.*/node_modules/.*
.*/flow-typed/.*
.*/build/.*
.*\.(test|spec)\.js
.*/build/.*
.*webpack.*
.*jest\.config\.js
<PROJECT_ROOT>/src/index\.js

[include]

[libs]

[lints]

[options]
all=true

[strict]

webpack.config.babel.js

import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import UglifyJsPlugin from 'uglifyjs-webpack-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';

const outputPath = path.resolve(__dirname, 'build');

export default {
  entry: './src/index.js',
  output: {
    filename: '[name].[hash].js',
    path: outputPath,
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.html$/,
        loader: 'html-loader',
      },
    ],
  },
  devServer: {
    contentBase: outputPath,
    compress: true,
    port: 3000,
  },
  devtool: 'eval-source-map',
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
    }),
    new CleanWebpackPlugin(),
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          compress: {
            drop_console: true,
          },
        },
      }),
      new OptimizeCSSAssetsPlugin(),
    ],
  },
};

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>My React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(, document.getElementById('root'));

index.css

* {
  margin: 0;
}

App.js

import React, { useState } from 'react';
import './App.css';

type Props = {
  initialCount: number,
};

function App({ initialCount }: Props) {
  const [count, setCount] = useState(initialCount);

  return (
    <div className="App" data-test="component-app">
      <header className="App-header">
        <p>My React App without Create React App!</p>
        <p>Count: {count}</p>
        <div>
          <button onClick={() => setCount(count + 1)}>+1</button>
          <button onClick={() => setCount(count - 1)}>-1</button>
          <button onClick={() => setCount(initialCount)}>clear</button>
        </div>
      </header>
    </div>
  );
}

App.defaultProps = {
  initialCount: 0,
};

export default App;

App.css

.App {
  text-align: center;
}

.App-header {
  background-color: #09d3ac;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 4vmin);
  color: white;
}

button {
  margin: 0 5px;
  padding: 10px;
  width: 200px;
  font-size: calc(10px + 4vmin);
  border-radius: 10px;
}

App.test.js

import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-16';
import App from './App';

Enzyme.configure({ adapter: new EnzymeAdapter() });

it('renders without crashing', () => {
  const wrapper = shallow(<App />);
  const appComponent = wrapper.find(`[data-test="component-app"]`);

  expect(wrapper).toBeTruthy();
  expect(appComponent.length).toBe(1);
});

完成です。

今回のWebpackの設定は開発用とプロダクション用で分けていませんが、実際には分けて作り、webpack-mergeなどを使って共通化すると良いでしょう。

今回のJestの設定は公式ドキュメントの通りにしてあります。

なお、EslintやPrettierもプロジェクトのスタイリングルールに応じて設定した方が良いでしょう。

動作確認

まずは開発環境を起動してみましょう。

$ yarn start
...
ℹ 「wds」: Project is running at http://localhost:3000/
...
ℹ 「wdm」: Compiled successfully.

ブラウザで「localhost:3000」が表示されます。

NewImage

カウンターの動作確認もしてみましょう。

NewImage

NewImage

NewImage

OKですね。

次に、テスト実行してみましょう。

$ yarn test
...
 PASS  src/App.test.js
  ✓ renders without crashing (10ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.667s
Ran all test suites.
✨  Done in 7.68s.

テストもパスしました。

最後に、ビルドしてみましょう。

$ yarn build
$ ls build/
index.html                     main.babca1870d3e34b4c183.css  main.babca1870d3e34b4c183.js

ビルドも成功しました。

これで、Reactの設定は完了しました。

Docker化する方法

それでは、Docker上で起動するようにしていきましょう。

ファイルの作成

必要なファイルを作成します。

$ touch Dockerfile.dev docker-compose.yml

設定を書く

Dockerの設定を書きましょう。

Dockerfile.dev

FROM node:12.10-alpine

WORKDIR /app

RUN apk update \
  && apk --no-cache add git ca-certificates wget

RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \
  && wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.30-r0/glibc-2.30-r0.apk \
  && apk --no-cache add glibc-2.30-r0.apk

COPY package.json .
COPY yarn.lock .
RUN yarn install

COPY .flowconfig .
RUN yarn global add flow-typed \
  && flow-typed install

COPY . .

EXPOSE 3000

CMD yarn start

docker-compose.yml

version: "3"

services:
  web:
    command: "yarn start --host 0.0.0.0 --port 3000"
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - /app/node_modules
      - .:/app

完成です。

FlowはAlpine上で実行する際に問題があり、こちらにissueが発行されています。結局、glibcを入れるか、flowのバイナリーを入れるかで対処する必要があり、今回は前者にしました。

動作確認

Dockerで起動できるか確認してみましょう。

$ docker-compose build --no-cache
$ docker-compose up -d
$ docker-compose ps
       Name                     Command               State           Ports         
------------------------------------------------------------------------------------
my-react-app_web_1   docker-entrypoint.sh yarn  ...   Up      0.0.0.0:3000->3000/tcp

ブラウザで「localhost:3000」を開けば、正しく表示されます。

これでDocker化まで完了しました。

おまけ

さらに、Webpackに開発用の設定を追加していきましょう。

画像を読み込むための設定

画像などのアセットを読み込むための設定を追加します。画像をWebpackで利用するには、url-loaderおよびfile-loaderのローダーを追加します。

$ yarn add --dev file-loader url-loader
$ vi webpack.config.babel.js
{
...
  module: {
    rules: [
...
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10 * 1024,
              name: '[name].[hash:8].[ext]',
              outputPath: 'assets',
            },
          },
        ],
      },
...
    ],
  },
...
}

「url-loader」でファイルをbase64に変換してCSSに埋め込みます。ファイルのサイズがリミットを超える場合は「file-loader」でファイルをそのまま読み込みます。base64はファイルを都度読み込む必要がないのでページの読み込みを早くできますが、常にファイルをそのまま扱いたい場合は「file-loader」だけで良いです。

Polyfillの設定方法

古いブラウザに対応するために、BabelにPolyfillを追加しましょう。

$ yarn add core-js@3

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ],
    "@babel/preset-react",
    "@babel/preset-flow"
  ]
}

@babel/polyfillはBabelの7.4.0から非推奨になっています。上記の設定で、必要なPolyfillだけをcorejsからインポートして使われるようになります。詳しくは、公式ドキュメントを参照して下さい。

HMR(Hot Module Replacement)の設定方法

webpack-dev-serverでは、デフォルトでdevServer.inlineが有効になっており、ライブリロードが実行されます。ライブリロードはソースコードを修正するたびにブラウザをリロードする機能ですが、一つのコンポーネントを修正するたびにブラウザをリロードするのは効率がよくありません。そこで、HMR(Hot Module Replacement)を有効することで、リロードすることなく、修正したコンポーネントだけ更新するようにしましょう。

webpack.config.babel.js (抜粋)

...
import webpack from 'webpack';
...

export default {
...
  devServer: {
    ...
    hot: true,
    ...
  },
...
  plugins: [
    ...
    new webpack.HotModuleReplacementPlugin(),
  ],
...
};

devServer.hotを有効にし、かつ、HotModuleReplacementPluginを設定しました。

起動してみると、以下のようにHMRが有効になっていることが分かります。

NewImage

react-hot-loaderの設定方法

Stateを保持したままコンポーネントの修正を反映するために、react-hot-loaderおよび@hot-loader/react-domを設定しましょう。

$ yarn add react-hot-loader @hot-loader/react-dom

.babelrc (抜粋)

{
  "plugins": ["react-hot-loader/babel"],
...
}

webpack.config.babel.js (抜粋)

...

export default {
...
  resolve: {
    alias: {
      'react-dom': '@hot-loader/react-dom',
    },
  },
};

App.js (抜粋)

...
import { hot } from 'react-hot-loader/root';
...
export default hot(App);

最後に

いかがでしたか?これでcreate-react-appに頼ることなく、自分でReactを設定できるようになったことでしょう。それでは。

環境

  • NodeJS: v12.11.0
  • Yarn: 1.17.3
  • Docker: 19.03.2
  • react: 16.10.0
  • react-dom: 16.10.0
  • react-hot-loader: 4.12.14
  • @hot-loader/react-dom: 16.9.0
  • core-js: 3
  • @babel/core: 7.6.2
  • @babel/preset-env: 7.6.2
  • @babel/preset-flow: 7.0.0
  • @babel/preset-react: 7.0.0
  • @babel/register: 7.6.2
  • babel-jest: 24.9.0
  • jest: 24.9.0
  • jest-enzyme: 7.1.1
  • enzyme: 3.10.0
  • enzyme-adapter-react-16: 1.14.0
  • flow-bin: 0.108.0
  • flow-typed: 2.6.1
  • webpack: 4.41.0
  • webpack-cli: 3.3.9
  • webpack-dev-server: 3.8.1
  • clean-webpack-plugin: 3.0.0
  • html-webpack-plugin: 3.2.0
  • optimize-css-assets-webpack-plugin: 5.0.3
  • uglifyjs-webpack-plugin: 2.2.0
  • mini-css-extract-plugin: 0.8.0
  • babel-loader: 8.0.6
  • css-loader: 3.2.0
  • html-loader: 0.5.5
  • url-loader: 2.2.0
  • file-loader: 4.2.0

カテゴリ : 技術 Tips & Tutorials タグ : babel, create-react-app, docker, flow, hot-module-replacement, polyfill, react, webpack

2019年7月22日 By KD コメントを書く

開発用データベースのためのDocker Composeの設定方法 (MySQL/PostgreSQL/MongoDB編)

開発用データベースのためのDocker Composeの設定方法 (MySQL/PostgreSQL/MongoDB編)

開発環境構築時にデータベースをDocker Composeを使って手軽に構築する方法を紹介します。

はじめに

開発環境構築はDockerで構築するのがもっと簡単です。そして、アプリケーションの開発のためにはローカル環境にデータベースを迅速に準備する必要があります。今回は、Docker Composeを使って、MySQL、PostgreSQL、MongoDBのデータベースを対象に、データベースを構築し、シードを準備する方法を紹介します。

前提条件

以下の準備が事前に完了している必要があります。

  • Dockerがインストールされていること

詳しくは「環境」を参照してください。

MySQLのDocker Composeによる設定とシードの追加

まずは、MySQLの設定方法です。

ベースの作成

必要なフォルダとファイルを作成します。

$ touch docker-compose.yml
$ mkdir -p mysql/initdb
$ touch mysql/initdb/1_create_tables.sql
$ touch mysql/initdb/2_insert_seed.sql

Docker Composeの設定ファイルとシード用SQLの作成

Docker Composeの設定ファイルとシードを入れいる簡単なSQLを作成します。

docker-compose.yml

version: '3'

services:
  mysql:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      TZ: "Asia/Tokyo"
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test_db
      MYSQL_USER: test
      MYSQL_PASSWORD: test
    ports:
      - 3306:3306
    volumes:
      - mysql:/var/lib/mysql
      - ./mysql/initdb:/docker-entrypoint-initdb.d

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - 8080:80
    environment:
      PMA_ARBITRARY: 1
      PMA_HOST: mysql
      PMA_USER: root
      PMA_PASSWORD: root
    depends_on:
      - mysql

volumes:
 mysql:

1_create_tables.sql

create table users
(
  id serial primary key,
  username varchar(50) unique not null,
  password varchar(50) not null,
  email varchar(255) unique not null
);

2_insert_seed.sql

insert into users (username, password, email) values ('keid', 'keidpass', 'keid@developer.com');
insert into users (username, password, email) values ('jobs', 'jobspass', 'jobs@developer.com');
insert into users (username, password, email) values ('mask', 'maskpass', 'mask@developer.com');

動作確認

それでは、Docker上でMySQLを起動してみましょう。

$ docker-compose up -d
$ docker-compose ps
          Name                        Command               State                 Ports              
-----------------------------------------------------------------------------------------------------
local-mysql_mysql_1        docker-entrypoint.sh --def ...   Up      0.0.0.0:3306->3306/tcp, 33060/tcp
local-mysql_phpmyadmin_1   /docker-entrypoint.sh apac ...   Up      0.0.0.0:8080->80/tcp  
$ mysql -h 0.0.0.0 -P 3306 -u test -p
Enter password: 
...
mysql> use test_db
...
mysql> select * from users;
+----+----------+----------+--------------------+
| id | username | password | email              |
+----+----------+----------+--------------------+
|  1 | keid     | keidpass | keid@developer.com |
|  2 | jobs     | jobspass | jobs@developer.com |
|  3 | mask     | maskpass | mask@developer.com |
+----+----------+----------+--------------------+
3 rows in set (0.01 sec)
mysql> exit
Bye

OKですね。

次に「http://localhost:8080/」にアクセスしてPhpMyAdminが動いていることも確認してみましょう。

NewImage

ばっちりですね。

PostgreSQLのDocker Composeによる設定とシードの追加

次に、PostgreSQLの設定方法です。

ベースの作成

必要なフォルダとファイルを作成します。

$ touch docker-compose.yml
$ mkdir -p postgres/initdb
$ touch postgres/initdb/1_create_tables.sql
$ touch postgres/initdb/2_insert_seed.sql

Docker Composeの設定ファイルとシード用SQLの作成

Docker Composeの設定ファイルとシードを入れいる簡単なSQLを作成します。

docker-compose.yml

version: '3'

services:
  postgres:
    image: postgres:11.4-alpine
    restart: always
    environment:
      TZ: "Asia/Tokyo"
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
      POSTGRES_DB: test_db
    ports:
      - 5432:5432
    volumes:
      - postgres:/var/lib/postgresql/data
      - ./postgres/initdb:/docker-entrypoint-initdb.d

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    ports:
      - 8080:80
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: admin
    volumes:
      - pgadmin:/var/lib/pgadmin
    depends_on:
      - postgres

volumes:
  postgres:
  pgadmin:

1_create_tables.sql

create table users
(
  id serial primary key,
  username varchar(50) unique not null,
  password varchar(50) not null,
  email varchar(255) unique not null
);

2_insert_seed.sql

insert into users (username, password, email) values ('keid', 'keidpass', 'keid@developer.com');
insert into users (username, password, email) values ('jobs', 'jobspass', 'jobs@developer.com');
insert into users (username, password, email) values ('mask', 'maskpass', 'mask@developer.com');

動作確認

それでは、Docker上でPostgreSQLを起動してみましょう。

$ docker-compose up -d
$ docker-compose ps
          Name                         Command              State               Ports            
-------------------------------------------------------------------------------------------------
local-postgres_pgadmin_1    /entrypoint.sh                  Up      443/tcp, 0.0.0.0:8080->80/tcp
local-postgres_postgres_1   docker-entrypoint.sh postgres   Up      0.0.0.0:5432->5432/tcp 
$ psql -h 0.0.0.0 -p 5432 -d test_db -U test
Password for user test: 
...
test_db=# select * from users;
 id | username | password |       email        
----+----------+----------+--------------------
  1 | keid     | keidpass | keid@developer.com
  2 | jobs     | jobspass | jobs@developer.com
  3 | mask     | maskpass | mask@developer.com
(3 rows)
test_db=# \q

大丈夫ですね。

次に「http://localhost:8080/」にアクセスしてpgAdminが動いていることも確認してみましょう。

NewImage

起動は問題なかったので、「新しいサーバを追加」からデータベースに接続します。

NewImage

ホスト名、ポート番号、ユーザ名、パスワードを入力して、「保存」をクリックします。

NewImage

データベースを選択して、ユーザを表示してみます。

NewImage

シードもちゃんと入っていますね。

なお、今回はpgAdminのデータもボリュームに保存しているので、一旦接続情報を入力しておけば、Dockerを停止しても接続情報は保持されます。

MongoDBのDocker Composeによる設定とシードの追加

最後に、MongoDBの設定方法です。

ベースの作成

必要なフォルダとファイルを作成します。

$ touch docker-compose.yml
$ mkdir -p mongo/seed
$ touch mongo/seed/users.json

Docker Composeの設定ファイルとシード用JSONファイルの作成

Docker Composeの設定ファイルとシードとなるJSONファイルを作成します。

docker-compose.yml

version: '3'

services:
  mongo:
    image: mongo:4.0
    restart: always
    ports:
      - 27017:27017
    volumes:
      - mongo:/data/db

  mongo-seed:
    image: mongo:4.0
    command: mongoimport --host mongo:27017 --db test_db --collection users --type json --file /seed/users.json --jsonArray
    volumes:
      - ./mongo/seed:/seed
    depends_on:
      - mongo

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_SERVER: mongo
      ME_CONFIG_MONGODB_PORT: 27017
    depends_on:
      - mongo

volumes:
  mongo:

users.json

[
  {
    "username": "keid",
    "password": "keidpass",
    "email": "keid@developer.com"
  },
  {
    "username": "jobs",
    "password": "jobspass",
    "email": "jobs@developer.com"
  },
  {
    "username": "mask",
    "password": "maskpass",
    "email": "mask@developer.com"
  }
]

動作確認

それでは、Docker上でMongoDBを起動してみましょう。

$ docker-compose up -d
$ docker-compose ps
            Name                           Command               State             Ports          
--------------------------------------------------------------------------------------------------
local-mongodb_mongo-express_1   tini -- /docker-entrypoint ...   Up       0.0.0.0:8081->8081/tcp  
local-mongodb_mongo-seed_1      docker-entrypoint.sh mongo ...   Exit 0                           
local-mongodb_mongo_1           docker-entrypoint.sh mongod      Up       0.0.0.0:27017->27017/tcp
$ mongo --port 27017
...
> use test_db
switched to db test_db
> db
test_db
> show collections
users
> db.users.find()
{ "_id" : ObjectId("5d317fda80a257d9f5c44379"), "username" : "keid", "password" : "keidpass", "email" : "keid@developer.com" }
{ "_id" : ObjectId("5d317fda80a257d9f5c4437a"), "username" : "mask", "password" : "maskpass", "email" : "mask@developer.com" }
{ "_id" : ObjectId("5d317fda80a257d9f5c4437b"), "username" : "jobs", "password" : "jobspass", "email" : "jobs@developer.com" }
> exit
bye

次に「http://localhost:8081/」にアクセスしてMongo Expressが動いていることも確認してみましょう。

NewImage

OKです。データも入っていますね。

おまけ(PrismaのDocker Composeの自動生成とシードの追加)

ベースの作成

Prismaの場合はコマンドラインからDocker Composeの設定を自動生成できます。

$ npm i -g prisma
$ prisma init prisma
? Set up a new Prisma server or deploy to an existing server? Create new database
? What kind of database do you want to deploy to? MySQL
? Select the programming language for the generated Prisma client Prisma JavaScript Client
...
$ cd prisma/
$ touch seed.graphql
$ tree
.
├── datamodel.prisma
├── docker-compose.yml
├── generated
│   └── prisma-client
│       ├── index.d.ts
│       ├── index.js
│       └── prisma-schema.js
├── prisma.yml
└── seed.graphql

Docker Composeの設定ファイルGraphQLファイルの作成

Docker Composeの設定ファイルとスキーマとシードのGraphQLファイルを作成します。

docker-compose.yml

version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.34
    restart: always
    ports:
    - "4466:4466"
    environment:
      PRISMA_CONFIG: |
        port: 4466
        databases:
          default:
            connector: mysql
            host: mysql
            user: root
            password: prisma
            rawAccess: false
            port: 3306
            migrations: false
  mysql:
    image: mysql:5.7
    restart: always
    ports:
    - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: prisma
    volumes:
      - mysql:/var/lib/mysql
volumes:
  mysql:

「rawAccess」と「migrations」をfalseにするのと、MySQLのポートの開放をします。

prisma.yml

endpoint: http://localhost:4466
datamodel: datamodel.prisma

generate:
  - generator: javascript-client
    output: ./generated/prisma-client/

seed:
  import: seed.graphql

hooks:
  post-deploy:
    - prisma generate

datamodel.prisma

type User {
  id: ID! @id
  username: String!
  password: String!
  email: String!
}

seed.graphql

mutation {
  user1: createUser(
    data: {
      username: "keid"
      password: "keidpass"
      email: "keid@developer.com"
    }
  ) {
    id
  }

  user2: createUser(
    data: {
      username: "jobs"
      password: "jobspass"
      email: "jobs@developer.com"
    }
  ) {
    id
  }

  use3: createUser(
    data: {
      username: "mask"
      password: "maskpass"
      email: "mask@developer.com"
    }
  ) {
    id
  }
}

動作確認

それでは、Docker上でPrismaを起動してみましょう。

$ docker-compose up -d
$ docker-compose ps
     Name                   Command             State                 Ports              
-----------------------------------------------------------------------------------------
prisma_mysql_1    docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp, 33060/tcp
prisma_prisma_1   /bin/sh -c /app/start.sh      Up      0.0.0.0:4466->4466/tcp 
$ prisma deploy
$ mysql -h 0.0.0.0 -P 3306 -u root -p
Enter password: 
...
mysql> use default@defaut;
...
mysql> show tables;
+---------------------------+
| Tables_in_default@default |
+---------------------------+
| User                      |
+---------------------------+
1 row in set (0.00 sec)
mysql> select * from User;
+---------------------------+----------+----------+--------------------+
| id                        | username | password | email              |
+---------------------------+----------+----------+--------------------+
| cjy9vplln000k07357qmb4lkn | keid     | keidpass | keid@developer.com |
| cjy9vplny000o0735ua7ab9w5 | jobs     | jobspass | jobs@developer.com |
| cjy9vploa000s0735xt18lpmu | mask     | maskpass | mask@developer.com |
+---------------------------+----------+----------+--------------------+
3 rows in set (0.00 sec)
mysql> exit
Bye

次に「http://localhost:4466/」にアクセスしてGraphQLで確認してみましょう。

NewImage

OKですね。

さらに「prisma admin」を実行するか、または「http://localhost:4466/_admin」にアクセスしてAdminページで確認してみましょう。

NewImage

こちらも問題ないですね。

最後に

いかがでしたか?これで、Docker Composeでローカルに開発用のデータベースを簡単に構築できるようになったことでしょう。それでは。

環境

  • Docker: 18.09.2
  • Docker Compose: 1.23.2
  • NPM: 6.10.0
  • Prisma: 1.34.1

カテゴリ : 技術 Tips & Tutorials タグ : database, docker, docker-compose, mongodb, mysql, postgresql, prisma

  • « 前のページ
  • 1
  • 2
  • 3
  • 4
  • …
  • 34
  • 次のページ »

ブログ更新情報や海外の関連情報などを配信する無料メルマガ

Sponsored Links

About Author

KD

世界を旅し日本を愛するエンジニア。大学でコンピュータサイエンスの楽しさを学び、日本の大手IT企業で働く中で、新しい技術やスケールするビジネスが北米にある事に気づく。世界に挑戦するための最大の壁が英語であったため、フィリピン留学およびカナダ留学を経て英語を上達させた。現在は日本在住でエンジニアとして働きつつ、次の挑戦に備えて世界の動向を注視している。挑戦に終わりはない。このブログでは、エンジニアやデザイナー向けの技術情報から、海外に留学したい人向けの留学情報、海外に興味がある人向けの海外旅行情報など、有益な情報を提供しています。

https://casualdevelopers.com/

最近の投稿

  • 2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年1月13日
  • 今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    2019年11月4日
  • ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    2019年10月30日
  • BashからZshに移行する方法(Mac編)

    BashからZshに移行する方法(Mac編)

    2019年10月21日
  • Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    2019年9月30日

カテゴリ

  • 技術 Tips & Tutorials (100)
  • 技術塾 (6)
  • ライフハック (26)
  • 海外留学 (12)
  • 英語学習 (3)
  • コラム (6)

アーカイブ

最高の学習のために

人気記事ランキング

  • MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
    MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
  • Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
    Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
  • SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
    SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
  • Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
    Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
  • SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
    SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
  • Amazon EC2インスタンスにSSHできなくなった時の対処法
    Amazon EC2インスタンスにSSHできなくなった時の対処法
  • SpringBootのProfile毎にプロパティを使い分ける3つの方法
    SpringBootのProfile毎にプロパティを使い分ける3つの方法
  • [tips][perl] Perlで文字コードをいい感じに処理する方法
    [tips][perl] Perlで文字コードをいい感じに処理する方法
  • 爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
    爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
  • Go言語のためのVisual Studio Codeの設定方法
    Go言語のためのVisual Studio Codeの設定方法

Bitcoin寄付 / BTC Donation

Bitcoinを寄付しよう

BTC
Select Payment Method
Personal Info

Donation Total: BTC 0.0010

このブログの運営のためにBitcoinでの寄付を募集しています。お気持ち程度の寄付を頂けると管理者の励みになります。

Bitcoin寄付について知りたい方はこちらの記事へ

ビットコイン取引ならここ

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • サイトマップ
  • タグ一覧
  • プライバシーポリシー
  • お問い合わせ

Copyright © 2023 KD - Casual Developers Notes