macOS開発環境導入メモ

# 更新履歴

2021/10/15 docker-desktopに変わるLimaを用いたやり方を発見したため追記
2021/10/05 docker-machineが廃止されたため、回避策が消滅。そのため、dockerは素直にdocker-desktopを使用(´・ω・)
※ ソースは、githubにあるため、やり方として一応残してはおきます。
※ [docker-machineの廃止](https://matsuand.github.io/docs.docker.jp.onthefly/machine/)

2021/09/22 docker有料化に伴う回避策
※ 払えるのなら、Dockerへお金を払いましょう
※ 社用のMacがIntel版だから上手くいってました。M1はうまくいきまへん。

# 事のきっかっけ
毎回調べてコマンド打つのがめんどくさくなった。
シェルスクリプト化をしてそろそろ纏めておいた方が良いと思った。

# 本題

## 主な使用ソフトウェアとか

- HomeBrew

macOS用のパッケージマネージャー。or Linuxと書いてあったのでLinuxも使える。
Windows? 知らん。Chocolateyでも使ってな。

- iTerm2

ターミナル系の便利なソフトウェア。
高給取りは皆使ってそうなイメージ。(偏見)

- Visual Studio Code

Microsoft社が開発しているソフトウェア。何故かリリースノート内にあるGifに出てくるインターフェイスがmacOSになってる。内部でWindows信仰心が足りない人がいるのかも....?

- Jetbrains

非常に便利な統合開発環境(以後、IDE)の開発している会社。チェコのプラハに本社ある。
AngularならWebStorm、ScalaならIntellijIDEA、SwiftならAppCodeといった具合に多種多様なソフトウェアを展開している。確か、Kotlinを作った会社だったはず。
プラグインも充実しているが、最近になってMaterial UIプラグインが有料化してションボリ。

- Alfred

非常に便利な検索ツール。ファイルも検索できる優れもの。


## 実行シェルコマンド

サクッと作っただけなので、見苦しいコードになっている件は悪しからず。

### Homebrew
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
```

### oh-my-zsh
```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

### 諸々のソフトウェア
```
brew install clipy
brew install iterm2
brew install visual-studio-code
brew install jetbrains-toolbox
brew install --cask Alfred
brew install imagemagick

brew install zsh-syntax-highlighting
echo '# zsh-syntax-highlighting' >> ~/.zshrc 
echo 'source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh' >> ~/.zshrc

brew install zsh-completions
echo '# zsh-completions' >> ~/.zshrc
echo 'if type brew &>/dev/null; then' >> ~/.zshrc
echo '  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH' >> ~/.zshrc
echo '  autoload -Uz compinit' >> ~/.zshrc
echo '  compinit' >> ~/.zshrc
echo 'fi' >> ~/.zshrc

brew install zsh-autosuggestions
echo '# zsh-autosuggestions' >> ~/.zshrc
echo 'source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh' >> ~/.zshrc

source ~/.zshrc
rm -f ~/.zcompdump; compinit
```

### SDKMAN
```
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
```

### nodebrew
```
brew install nodebrew
mkdir -p ~/.nodebrew/src
echo '# Nodebrew' >> ~/.zshrc
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
```

### docker (有料化に伴う回避)
※ 事前に、Macの " ~/.docker " フォルダを削除しておくこと
#### 1.Lima
```shell
brew install lima docker docker-compose
curl -o default.yaml https://raw.githubusercontent.com/lima-vm/lima/master/pkg/limayaml/default.yaml
```
##### default.yamlを編集
<details><summary>default.yaml(ダウンロード時)</summary><div>

```yaml
# ===================================================================== #
# BASIC CONFIGURATION
# ===================================================================== #

# Arch: "default", "x86_64", "aarch64".
# "default" corresponds to the host architecture.
arch: "default"

# An image must support systemd and cloud-init.
# Ubuntu and Fedora are known to work.
# Default: none (must be specified)
images:
  # Try to use a local image first.
  - location: "~/Downloads/hirsute-server-cloudimg-amd64.img"
    arch: "x86_64"
  - location: "~/Downloads/hirsute-server-cloudimg-arm64.img"
    arch: "aarch64"

  # Download the file from the internet when the local file is missing.
  # Hint: run `limactl prune` to invalidate the "current" cache
  - location: "https://cloud-images.ubuntu.com/hirsute/current/hirsute-server-cloudimg-amd64.img"
    arch: "x86_64"
  - location: "https://cloud-images.ubuntu.com/hirsute/current/hirsute-server-cloudimg-arm64.img"
    arch: "aarch64"

# CPUs: if you see performance issues, try limiting cpus to 1.
# Default: 4
cpus: 4

# Memory size
# Default: "4GiB"
memory: "4GiB"

# Disk size
# Default: "100GiB"
disk: "100GiB"

# Expose host directories to the guest, the mount point might be accessible from all UIDs in the guest
# Default: none
mounts:
  - location: "~"
    # CAUTION: `writable` SHOULD be false for the home directory.
    # Setting `writable` to true is possible, but untested and dangerous.
    writable: false
  - location: "/tmp/lima"
    writable: true

ssh:
  # A localhost port of the host. Forwarded to port 22 of the guest.
  # Default: 0 (automatically assigned to a free port)
  localPort: 0
  # Load ~/.ssh/*.pub in addition to $LIMA_HOME/_config/user.pub .
  # This option is useful when you want to use other SSH-based
  # applications such as rsync with the Lima instance.
  # If you have an insecure key under ~/.ssh, do not use this option.
  # Default: true
  loadDotSSHPubKeys: true



# ===================================================================== #
# ADVANCED CONFIGURATION
# ===================================================================== #

containerd:
  # Enable system-wide (aka rootful)  containerd and its dependencies (BuildKit, Stargz Snapshotter)
  # Default: false
  system: false
  # Enable user-scoped (aka rootless) containerd and its dependencies
  # Default: true
  user: true
#  # Override containerd archive
#  # Default: hard-coded URL with hard-coded digest (see the output of `limactl info | jq .defaultTemplate.containerd.archives`)
#  archives:
#    - location: "~/Downloads/nerdctl-full-X.Y.Z-linux-amd64.tar.gz"
#      arch: "x86_64"
#      digest: "sha256:..."

# Provisioning scripts need to be idempotent because they might be called
# multiple times, e.g. when the host VM is being restarted.
# provision:
#   # `system` is executed with the root privilege
#   - mode: system
#     script: |
#       #!/bin/bash
#       set -eux -o pipefail
#       export DEBIAN_FRONTEND=noninteractive
#       apt-get install -y vim
#   # `user` is executed without the root privilege
#   - mode: user
#     script: |
#       #!/bin/bash
#       set -eux -o pipefail
#       cat <<EOF > ~/.vimrc
#       set number
#       EOF

# probes:
#  # Only `readiness` probes are supported right now.
#  - mode: readiness
#    description: vim to be installed
#    script: |
#       #!/bin/bash
#       set -eux -o pipefail
#       if ! timeout 30s bash -c "until command -v vim; do sleep 3; done"; then
#         echo >&2 "vim is not installed yet"
#         exit 1
#       fi
#    hint: |
#      vim was not installed in the guest. Make sure the package system is working correctly.
#      Also see "/var/log/cloud-init-output.log" in the guest.

# ===================================================================== #
# FURTHER ADVANCED CONFIGURATION
# ===================================================================== #

firmware:
  # Use legacy BIOS instead of UEFI.
  # Default: false
  legacyBIOS: false

video:
  # QEMU display, e.g., "none", "cocoa", "sdl".
  # As of QEMU v5.2, enabling this is known to have negative impact
  # on performance on macOS hosts: https://gitlab.com/qemu-project/qemu/-/issues/334
  # Default: "none"
  display: "none"

# The instance can get routable IP addresses from the vmnet framework using
# https://github.com/lima-vm/vde_vmnet.
networks:
  # Lima can manage daemons for networks defined in $LIMA_HOME/_config/networks.yaml
  # automatically. Both vde_switch and vde_vmnet binaries must be installed into
  # secure locations only alterable by the "root" user.
  # - lima: shared
  #   # MAC address of the instance; lima will pick one based on the instance name,
  #   # so DHCP assigned ip addresses should remain constant over instance restarts.
  #   macAddress: ""
  #   # Interface name, defaults to "lima0", "lima1", etc.
  #   interface: ""
  #
  # Lima can also connect to "unmanaged" vde networks addressed by "vnl". This
  # means that the daemons will not be controlled by Lima, but must be started
  # before the instance.  The interface type (host, shared, or bridged) is
  # configured in vde_vmnet and not in lima.
  # vnl (virtual network locator) points to the vde_switch socket directory,
  # optionally with vde:// prefix
  # - vnl: "vde:///var/run/vde.ctl"
  #   # VDE Switch port number (not TCP/UDP port number). Set to 65535 for PTP mode.
  #   # Default: 0
  #   switchPort: 0
  #   # MAC address of the instance; lima will pick one based on the instance name,
  #   # so DHCP assigned ip addresses should remain constant over instance restarts.
  #   macAddress: ""
  #   # Interface name, defaults to "lima0", "lima1", etc.
  #   interface: ""

# Port forwarding rules. Forwarding between ports 22 and ssh.localPort cannot be overridden.
# Rules are checked sequentially until the first one matches.
# portForwards:
#   - guestPort: 443
#     hostIP: "0.0.0.0" # overrides the default value "127.0.0.1"; allows privileged port forwarding
#   # default: hostPort: 443 (same as guestPort)
#   # default: guestIP: "127.0.0.1" (also matches bind addresses "0.0.0.0", "::", and "::1")
#   # default: proto: "tcp" (only valid value right now)
#   - guestPortRange: [4000, 4999]
#     hostIP:  "0.0.0.0" # overrides the default value "127.0.0.1"
#   # default: hostPortRange: [4000, 4999] (must specify same number of ports as guestPortRange)
#   - guestPort: 80
#     hostPort: 8080 # overrides the default value 80
#   - guestIP: "127.0.0.2" # overrides the default value "127.0.0.1"
#     hostIP: "127.0.0.2" # overrides the default value "127.0.0.1"
#   # default: guestPortRange: [1, 65535]
#   # default: hostPortRange: [1, 65535]
#   - guestPort: 8888
#     ignore: true (don't forward this port)
#   # Lima internally appends this fallback rule at the end:
#   - guestIP: "127.0.0.1"
#     guestPortRange: [1, 65535]
#     hostIP: "127.0.0.1"
#     hostPortRange: [1, 65535]
#   # Any port still not matched by a rule will not be forwarded (ignored)

# Extra environment variables that will be loaded into the VM at start up.
# These variables are consumed by internal init scripts, and also added
# to /etc/environment.
# If you set any of "ftp_proxy", "http_proxy", "https_proxy", or "no_proxy", then
# Lima will automatically set an uppercase variant to the same value as well.
# env:
#   KEY: value

# The host agent implements a DNS server that looks up host names on the host
# using the local system resolver. This means changing VPN and network settings
# are reflected automatically into the guest, including conditional forward,
# and mDNS lookup:
# Default: true
useHostResolver: true

# If useHostResolver is false, then the following rules apply for configuring dns:
# Explicitly set DNS addresses for qemu user-mode networking. By default qemu picks *one*
# nameserver from the host config and forwards all queries to this server. On macOS
# Lima adds the nameservers configured for the "en0" interface to the list. In case this
# still doesn't work (e.g. VPN setups), the servers can be specified here explicitly.
# If nameservers are specified here, then the "en0" configuration will be ignored.
# dns:
# - 1.1.1.1
# - 1.0.0.1

# ===================================================================== #
# END OF TEMPLATE
# ===================================================================== #


```

</div>

<details><summary>編集箇所</summary><div>

```yaml
# ===================================================================== #
# BASIC CONFIGURATION
# ===================================================================== #

# Arch: "default", "x86_64", "aarch64".
# "default" corresponds to the host architecture.
arch: "x86_64" # ← defaultをx86_64に書き換える
```

</div>

##### docker環境の構築

```shell
# Lima 起動
# (最後にFATA[0673] did not receive an event with the "running" status)
# って出るけど、自分は気にしない方向で。
limactl start default.yaml
Proceed with the default configuration を選択

limactl list

# NAME       STATUS     SSH                ARCH      DIR
# default    Running    127.0.0.1:60022    x86_64    /Users/[username]/.lima/default

# Docker Port
echo  "export DOCKER_HOST='tcp://127.0.0.1:2375'" >> ~/.zshrc
source ~/.zshrc

※以後の「instance名」とは、limactl listで出てくるNAMEのこと。上記で言うところの、「default」が該当する。
# Docker Engine Server
curl -fsSL https://get.docker.com | limactl shell [instance名]

# add user group
limactl shell [instance名] whoami # lima が出力される場合がある
limactl shell [instance名] sudo gpasswd -a [上記、出力されたユーザー名] docker
ex) limactl shell [instance名] sudo gpasswd -a lima docker
limactl stop [instance名] ; sleep 5; limactl start [instance名] 

# docker version
limactl shell [instance名] docker version
#Client: Docker Engine - Community
# Version:           20.10.9
# API version:       1.41
# Go version:        go1.16.8
# Git commit:        c2ea9bc
# Built:             Mon Oct  4 16:08:41 2021
# OS/Arch:           linux/amd64
# Context:           default
# Experimental:      true

# create daemon.json
limactl shell [instance名] sudo vim /etc/docker/daemon.json
# 下記を追記
---[記入]---
{"hosts": ["tcp://127.0.0.1:2375", "unix:///var/run/docker.sock"]}
---[ここまで]----

# docker override
limactl shell [instance名] sudo mkdir -p /etc/systemd/system/docker.service.d/
limactl shell [instance名] sudo vim /etc/systemd/system/docker.service.d/override.conf

# 下記を追記
---[記入]---
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
---[ここまで]----

# docker service reboot
limactl shell [instance名] sudo systemctl daemon-reload
limactl shell [instance名] sudo systemctl restart docker.service
```

##### docker動作確認

```shell
docker version

# macOS側
# Client: Docker Engine - Community
#  Version:           20.10.9
#  API version:       1.41
#  Go version:        go1.17.1
#  Git commit:        c2ea9bc90b
#  Built:             Thu Sep 23 18:26:34 2021
#  OS/Arch:           darwin/arm64
#  Context:           default
#  Experimental:      true

# Lima側
# Server: Docker Engine - Community
#  Engine:
#   Version:          20.10.9
#   API version:      1.41 (minimum version 1.12)
#   Go version:       go1.16.8
#   Git commit:       79ea9d3
#   Built:            Mon Oct  4 16:06:48 2021
#   OS/Arch:          linux/amd64
#   Experimental:     false
#  containerd:
#   Version:          v1.5.7
#   GitCommit:        8686ededfc90076914c5238eb96c883ea093a8ba
#  runc:
#   Version:          1.0.2
#   GitCommit:        v1.0.2-0-g52b36a2d
#  docker-init:
#   Version:          0.19.0
#   GitCommit:        de40ad0
```

##### lima 操作

```shell
limactl ls # lima vm 一覧

limactl start xxxx(or xxxxx.yml) vm 起動

limactl stop xxxx vm 停止

limactl delete xxxx 削除
```

#### 2. docker-machine
※ Cisco AnyConnect VPNといったVPNソフトウェアが動いていると、正しく動作しない。

```shell
## docker構築
brew install docker
brew install docker-machine
brew install docker-compose
brew install --cask virtualbox

docker-machine create --driver virtualbox [任意のイメージ名]
ex) docker-machine create --driver virtualbox default
docker-machine restart
eval "$(docker-machine env [上で入力した任意のイメージ名])"
ex) eval "$(docker-machine env default)"

## Docker-machine image 起動・停止
docker-machine start [任意のイメージ名]
ex) docker-machine start default
docker-machine stop [任意のイメージ名]
ex) docker-machine stop default
```

#### 3. その他
```shell
## Docker image 削除
docker rmi -f  $(docker images -a -q)

## Docker-machine image 削除
docker-machine rm [イメージ名]
ex) docker-machine rm default
```

### Zenith (Windowsで言うCrystalDiskInfoみたいなやつ)
```
brew install zenith
```

## macOS のシステム設定
### キー入力で連打できるようにする
```
defaults write -g ApplePressAndHoldEnabled -bool false
```

## 参考記事

[Docker Desktop for Macの実用的な代替手段: lima + Docker](https://qiita.com/yoichiwo7/items/44aff38674134ad87da3)