0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Cursorエディター導入」Docker開発環境で快適に使うための工夫

Last updated at Posted at 2025-04-19

はじめに

CursorをDockerコンテナにアタッチして開発している方も多いかと思います。

通常は拡張機能を手動でインストールしているケースが多いですが、実務ではDockerイメージを削除・再構築する機会も多く、そのたびに拡張機能を手動で再インストールするのは面倒ですよね。

チームで開発する際に、できるだけエディターの設定も統一したいです。
そこで今回は、実務レベルでチーム開発に対応できるように、Cursorエディターの設定や拡張機能のインストールを自動化してみました。

VSCode を長く使っている方は、プロジェクトごとに「ワークスペース設定」を行っていることが多いかと思います。
プロジェクト直下に .vscode/settings.json を配置することで、ワークスペース単位で設定を上書きすることが可能です。

今回は、Cursor が比較的新しいエディターであり、まだ使い慣れていない方も多いと思いますので、ユーザー設定を直接編集する方法 をご紹介しています。

お題

今回、以下の4つの課題を解決することを目的としました

  • Cursor エディターの settings.json をチームで共有し、自動で適用できるようにしたい
  • Mac ローカル環境に Cursor エディターの拡張機能を一括インストールしたい
  • 一部の拡張機能が Marketplace 経由ではインストールできない問題がある
  • Docker コンテナ内でも拡張機能を自動でインストールしたい

課題

事前準備

まず、Cursor エディターの settings.json ファイルを作成します。
この設定方法については、以前の記事で紹介していますので、詳しくはこちらをご覧ください:
👉 【Cursorエディター導入/第一歩】Cursorエディターを触ってみました

editor_settings.json
{
    "workbench.colorTheme": "Default Dark+",
    "window.newWindowDimensions": "inherit",
    "extensions.verifySignature": false,
    "window.commandCenter": true,
    "emmet.triggerExpansionOnTab": true,
    "search.showLineNumbers": true,
    "files.insertFinalNewline": true,
    "files.trimFinalNewlines": true,
    "files.trimTrailingWhitespace": true,
    "editor.minimap.enabled": true,
    "editor.copyWithSyntaxHighlighting": true,
    "breadcrumbs.enabled": true,
    "editor.tabSize": 2,
    "editor.linkedEditing": true,
    "emmet.variables": {
        "lang": "ja"
    },
    "editor.guides.indentation": true,
    "editor.guides.bracketPairsHorizontal": true,
    "editor.bracketPairColorization.independentColorPoolPerBracketType": true,
    "editor.roundedSelection": true,
    "editor.renderWhitespace": "all",
    "editor.wordWrap": "on",
    "editor.wordWrapColumn": 140,
    "editor.wrappingIndent": "same",
    "editor.tabCompletion": "on",
    "editor.snippetSuggestions": "top",
    "editor.formatOnType": true,
    "editor.formatOnPaste": true,
    "editor.quickSuggestions": {
        "comments": "on",
        "strings": "on"
    },
    "files.autoGuessEncoding": true,
    "editor.fontFamily": "'Fira Code', 'Cica', 'monospace'",
    "editor.fontWeight": "500",
    "editor.fontSize": 13,
    "editor.letterSpacing": -0.4,
    "editor.lineHeight": 1.4,
    "editor.tokenColorCustomizations": {
        "comments": "#5da33c"
    },
    "files.associations": {
        "*.mdc": "markdown"
    },
    "workbench.editorAssociations": {
        "*.mdc": "default"
    },
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true,
    "prettier.printWidth": 140,
    "prettier.singleLine": true,
    "prettier.bracketSpacing": true,
    "prettier.arrowParens": "always",
    "prettier.semi": true,
    "prettier.singleQuote": false,
    "prettier.trailingComma": "es5",
    "prettier.useTabs": false,
    "prettier.tabWidth": 2,
    "prettier.endOfLine": "lf",
    "prettier.bracketSameLine": false,
    "prettier.singleAttributePerLine": false,
    "prettier.jsxSingleQuote": false,
    "prettier.tailwindPreserveWhitespace": true,
    "prettier.plugins": [
        "prettier-plugin-tailwindcss",
        "prettier-plugin-sort-json",
        "@ianvs/prettier-plugin-sort-imports"
    ],
    "prettier.importOrder": [
        "<BUILTIN_MODULES>",
        "<THIRD_PARTY_MODULES>",
        "",
        "^@/(.*)$",
        "^[./]",
        "",
        "<TYPES>",
        "<TYPES>^[./]"
    ],
    "workbench.activityBar.orientation": "vertical",
    "workbench.iconTheme": "vscode-icons",
    "workbench.tree.indent": 16,
    "workbench.tree.renderIndentGuides": "always",
    "workbench.reduceMotion": "on",
    "workbench.colorCustomizations": {
        "editorIndentGuide.background1": "#cb997e",
        "editorIndentGuide.background2": "#ddbea9",
        "editorIndentGuide.background3": "#ffe8d6",
        "editorIndentGuide.background4": "#b7b7a4",
        "editorIndentGuide.background5": "#a5a58d",
        "editorIndentGuide.background6": "#6b705c",
        "editorIndentGuide.activeBackground1": "#06d6a0",
        "editorIndentGuide.activeBackground2": "#06d6a0",
        "editorIndentGuide.activeBackground3": "#06d6a0",
        "editorIndentGuide.activeBackground4": "#06d6a0",
        "editorIndentGuide.activeBackground5": "#06d6a0",
        "editorIndentGuide.activeBackground6": "#06d6a0",
        "tab.activeBackground": "#563b90",
        "tab.activeForeground": "#d3d2d4",
        "statusBar.background": "#53208c"
    },
    "search.exclude": {
        "**/idea": true
    },
    "[python]": {
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.fixAll": "explicit",
            "source.organizeImports": "explicit"
        },
        "editor.defaultFormatter": "charliermarsh.ruff",
        "editor.suggestSelection": "first",
        "editor.snippetSuggestions": "top",
        "editor.suggest.localityBonus": true,
        "editor.suggest.shareSuggestSelections": true,
        "editor.suggest.preview": true,
        "editor.tabSize": 4
    },
    "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features",
        "editor.formatOnSave": true,
        "editor.formatOnSaveMode": "file",
        "editor.tabSize": 4
    },
    "[markdown]": {
        "editor.defaultFormatter": "vscode.markdown-language-features",
        "files.trimTrailingWhitespace": false,
        "editor.formatOnSave": true,
        "editor.formatOnSaveMode": "file"
    },
    "[html]": {
        "editor.defaultFormatter": "vscode.html-language-features"
    },
    "[javascript, typescript, typescriptreact, json]": {
        "editor.defaultFormatter": "vscode.typescript-language-features",
        "editor.codeActionsOnSave": {
            "source.organizeImports": "explicit"
        },
        "editor.formatOnSave": true,
        "editor.tabSize": 2
    },
    "[terraform]": {
        "editor.codeActionsOnSave": {
            "source.organizeImports": "explicit"
        },
        "editor.defaultFormatter": "hashicorp.terraform",
        "editor.formatOnSave": true,
        "editor.tabSize": 4
    },
    "[terraform-vars]": {
        "editor.codeActionsOnSave": {
            "source.organizeImports": "explicit"
        },
        "editor.defaultFormatter": "hashicorp.terraform",
        "editor.formatOnSave": true,
        "editor.tabSize": 4
    },
    "files.exclude": {
        "**/.idea": true,
        "**/*_cache": true
    },
    "terminal.integrated.fontSize": 15,
    "terminal.integrated.lineHeight": 1.25,
    "terminal.integrated.defaultLocation": "editor",
    "remote.extensionKind": {
        "ms-ceintl.vscode-language-pack-ja": [
            "ui",
            "workspace"
        ],
        "ms-azuretools.vscode-docker": [
            "ui",
            "workspace"
        ],
        "anysphere.pyright": [
            "ui",
            "workspace"
        ],
        "esbenp.prettier-vscode": [
            "ui",
            "workspace"
        ],
        "ms-vscode.makefile-tools": [
            "ui",
            "workspace"
        ],
        "corschenzi.mermaid-graphical-editor": [
            "ui",
            "workspace"
        ]
    }
}

拡張機能リスト

editor_extensions.json
[
    {
        "name": "日本語言語パック",
        "identifier": "ms-ceintl.vscode-language-pack-ja",
        "version": "1.96.2024121109",
        "description": "日本語化するための言語パック"
    },
    {
        "name": "Docker",
        "identifier": "ms-azuretools.vscode-docker",
        "version": "1.29.4",
        "description": "Docker のビルド・起動・管理ツール"
    },
    {
        "name": "Dev Containers",
        "identifier": "ms-vscode-remote.remote-containers",
        "version": "0.394.0",
        "description": "コンテナ内での開発拡張機能"
    },
    {
        "name": "Cursor Pyright",
        "identifier": "anysphere.pyright",
        "version": "1.1.327",
        "description": "Cursor 向けの Pyright 拡張機能"
    },
    {
        "name": "VSCode Icons",
        "identifier": "vscode-icons-team.vscode-icons",
        "version": "12.11.0",
        "description": "VSCodeアイコン"
    },
    {
        "name": "Prettier",
        "identifier": "esbenp.prettier-vscode",
        "version": "11.0.0",
        "description": "Prettierによるコード整形"
    },
    {
        "name": "Tailwind CSS IntelliSense",
        "identifier": "bradlc.vscode-tailwindcss",
        "version": "0.14.15",
        "description": "Tailwind CSS のコード補完"
    },
    {
        "name": "Import Cost",
        "identifier": "wix.vscode-import-cost",
        "version": "3.3.0",
        "description": "インポートコストを表示する"
    },
    {
        "name": "Quokka.js",
        "identifier": "wallabyjs.quokka-vscode",
        "version": "1.0.711",
        "description": "Console の出力をエディタ上で確認する"
    },
    {
        "name": "Flutter Color",
        "identifier": "circlecodesolution.ccs-flutter-color",
        "version": "2.0.0",
        "description": "Flutter の色を管理する"
    },
    {
        "name": "Mermaid Graphical Editor",
        "identifier": "corschenzi.mermaid-graphical-editor",
        "version": "0.5.1",
        "description": "GUI サポート Mermaid の編集ツール"
    },
    {
        "name": "Makefile Tools",
        "identifier": "ms-vscode.makefile-tools",
        "version": "0.12.17",
        "description": "Makefile 開発支援ツール"
    },
    {
        "name": "HashiCorp Terraform",
        "identifier": "hashicorp.terraform",
        "version": "2.34.3",
        "description": "Terraform 拡張機能"
    },
    {
        "name": "Python",
        "identifier": "ms-python.python",
        "version": "2024.12.3",
        "description": "Python 拡張機能(実行・デバッグ・補完など)"
    },
    {
        "name": "Ruff",
        "identifier": "charliermarsh.ruff",
        "version": "2025.22.0",
        "description": "ruff 拡張機能"
    },
    {
        "name": "Cucumber (Gherkin) Full Support",
        "identifier": "alexkrechik.cucumberautocomplete",
        "version": "3.0.5",
        "description": "Gherkin 言語の開発サポート"
    }
]

現在のディレクトリと同じ階層に local_vsix という名前のフォルダーを作成してください。

このフォルダーには、Marketplace からダウンロードした .vsix ファイルを配置します。
拡張機能のインストールは基本的に Marketplace 経由が優先されるため、最初は空のフォルダーでも問題ありません。

local_vsix フォルダーに配置する .vsix ファイルのファイル名は、editor_extensions.json に記載されている identifier と同じ名前にしてください。

Cursorエディターの設定と拡張機能インストールを自動化する

こちらのスクリプトを実行すれば完全に自動化できます

initialize_cursor.sh
#!/bin/bash

set -euo pipefail

# 定数
EXT_JSON_FILE="editor_extensions.json"
SRC_SETTINGS_FILE="editor_settings.json"
DEST_SETTINGS_FILE="settings.json"
CURSOR_SETTING_PATH="${HOME}/Library/Application Support/Cursor/User"
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"
VSIX_DIR="${CURRENT_DIR}/local_vsix"

# Cursor確認
if ! command -v cursor &> /dev/null; then
    echo "❌ Cursorエディターがインストールされていません。"
    exit 1
fi

# settings.jsonのバックアップ & 設定ファイル上書き
if [ -f "${CURSOR_SETTING_PATH}/${DEST_SETTINGS_FILE}" ]; then
    today=$(date +%Y%m%d)
    cp "${CURSOR_SETTING_PATH}/${DEST_SETTINGS_FILE}" "${CURSOR_SETTING_PATH}/${DEST_SETTINGS_FILE}.bak-${today}"
    echo "📦 設定ファイルのバックアップを作成しました(.bak-${today})"
fi

cp "${CURRENT_DIR}/${SRC_SETTINGS_FILE}" "${CURSOR_SETTING_PATH}/${DEST_SETTINGS_FILE}"
echo "✅ cursor の settings.json を更新しました"

# 拡張機能のインストール
echo "🧩 拡張機能のインストールを開始します..."

# JSONを1行ずつ処理し、identifierとnameを取り出す
identifier=""
name=""
while read -r line; do
  # "identifier": "xxx" を抽出
  if [[ "$line" =~ \"identifier\"\:\ \"([^\"]+)\" ]]; then
    identifier="${BASH_REMATCH[1]}"
  fi

  # "name": "xxx" を抽出
  if [[ "$line" =~ \"name\"\:\ \"([^\"]+)\" ]]; then
    name="${BASH_REMATCH[1]}"
  fi

  # identifier がセットされていればインストール処理へ
  if [[ -n "${identifier:-}" ]]; then
    if cursor --list-extensions 2>/dev/null | grep -q "^${identifier}$"; then
      echo "🔁 ${name}${identifier})は既にインストール済みです。スキップします。"
    else
      echo "📦 ${name}${identifier})をインストール中..."
      if cursor --install-extension "${identifier}"; then
        echo "✅ ${name}${identifier})をインストールしました"
      else
        echo "ℹ️ Marketplaceからのインストールに失敗。ローカルのVSIXを確認します..."

        vsix_path="${VSIX_DIR}/${identifier}.vsix"
        if [[ -f "${vsix_path}" ]]; then
          echo "📦 ${name}${identifier})をVSIXでインストール中..."
          if cursor --install-extension "${vsix_path}"; then
            echo "✅ VSIXで ${name}${identifier})をインストールしました"
          else
            echo "❌ VSIXによる ${name}${identifier})のインストールにも失敗しました"
          fi
        else
          echo "❌ ${name}${identifier})のVSIXファイルが見つかりません(期待パス: ${vsix_path})"
        fi
      fi
    fi
    unset identifier name
  fi
done < "${CURRENT_DIR}/${EXT_JSON_FILE}"

これで、Makefile などに以下のような処理を記述すれば、Cursor エディターの設定を快適に行えるようになります。

.PHONY: init-cursor-editor
init-cursor-editor: ## Cursorエディターの設定を初期化
	@./initialize_cursor.sh

次回は、Dockerコンテナに拡張機能をインストールする方法をご紹介します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?