├── .devcontainer ├── cpu-uv │ ├── Dockerfile │ └── devcontainer.json ├── gpu-sagemaker │ ├── Dockerfile │ ├── devcontainer.json │ ├── init.sh │ └── requirements.txt └── gpu-uv │ ├── Dockerfile │ └── devcontainer.json ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── docs ├── coding-guidelines.md └── operation_ec2.md ├── img ├── cf-ec2-architecture.png └── vscode-ssm-ec2.png ├── ops_ec2 └── lambda_function.py ├── pyproject.toml ├── setup ├── cf-template │ └── cf-ec2.yaml ├── check_vm_env │ ├── check_cuda_torch.sh │ └── mnist_example │ │ ├── LICENSE │ │ └── mnist.py ├── coding_agent │ ├── claude-code │ │ ├── README.md │ │ └── setup_claude_code.sh │ └── cline │ │ ├── .clineignore │ │ ├── .clinerules │ │ └── README.md ├── make_new_project.sh ├── ssh │ ├── ssh_setup_linux.sh │ └── ssh_setup_win.bat └── vscode │ ├── vscode_local_setup_linux.sh │ ├── vscode_local_setup_win.bat │ ├── vscode_settings.json │ └── vscode_vm_setup.sh ├── src ├── __init__.py └── main.py └── uv.lock /.devcontainer/cpu-uv/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/astral-sh/uv:debian 2 | 3 | # Install awscli v2 4 | RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ 5 | && unzip awscliv2.zip \ 6 | && ./aws/install \ 7 | && rm -r aws \ 8 | && rm awscliv2.zip 9 | 10 | # Add non-root user 11 | ARG USERNAME=vscode 12 | ARG USER_UID=1000 13 | ARG USER_GID=$USER_UID 14 | 15 | # Install sudo and add non-root user 16 | RUN apt-get update \ 17 | && groupadd --gid $USER_GID $USERNAME \ 18 | && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ 19 | && apt-get install -y sudo \ 20 | && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ 21 | && chmod 0440 /etc/sudoers.d/$USERNAME 22 | 23 | # Switch to non-root user 24 | USER $USERNAME 25 | 26 | # Set working directory 27 | WORKDIR /home/$USERNAME/ 28 | 29 | # add ll alias 30 | RUN echo 'alias ll="ls -la"' >> ~/.bash_aliases 31 | -------------------------------------------------------------------------------- /.devcontainer/cpu-uv/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cpu-uv", // [Optional] Your project name here 3 | "build": { 4 | "dockerfile": "Dockerfile" 5 | }, 6 | "workspaceFolder": "/workspace", 7 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", 8 | "mounts": [ 9 | "source=uv-cache,target=/root/.cache/uv,type=volume", // uv cache 10 | "source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,consistency=cached" // git config 11 | ], 12 | "remoteEnv": { 13 | "UV_COMPILE_BYTECODE": "1", 14 | "UV_LINK_MODE": "copy" 15 | }, 16 | "postCreateCommand": "uv sync --frozen && . .venv/bin/activate && uv add pre-commit && uv run pre-commit install", 17 | // Configure tool-specific properties. 18 | "customizations": { 19 | // Configure properties specific to VS Code. 20 | "vscode": { 21 | "settings": { 22 | "terminal.integrated.profiles.linux": { 23 | "bash": { 24 | "path": "/bin/bash" 25 | } 26 | }, 27 | // notebook 28 | "notebook.formatOnSave.enabled": true, 29 | "notebook.codeActionsOnSave": { 30 | "notebook.source.fixAll": "explicit", 31 | "notebook.source.organizeImports": "explicit" 32 | }, 33 | // python 34 | "[python]": { 35 | "editor.formatOnSave": true, 36 | "editor.defaultFormatter": "charliermarsh.ruff", 37 | "editor.codeActionsOnSave": { 38 | "source.fixAll": "explicit", // fix lint violations on-save 39 | "source.organizeImports": "explicit" // organize imports on-save 40 | } 41 | }, 42 | "mypy-type-checker.args": [ 43 | "--config=${workspaceFolder}/pyproject.toml" 44 | ], 45 | "python.defaultInterpreterPath": "./.venv/bin/python", 46 | "python.analysis.typeCheckingMode": "basic", 47 | "python.analysis.inlayHints.functionReturnTypes": true, 48 | "python.analysis.inlayHints.variableTypes": true, 49 | "python.analysis.completeFunctionParens": true, 50 | // visibility 51 | "editor.bracketPairColorization.enabled": true, 52 | "editor.guides.bracketPairs": "active", 53 | // markdown 54 | "[markdown]": { 55 | "editor.wordWrap": "bounded", 56 | "editor.defaultFormatter": "esbenp.prettier-vscode" 57 | } 58 | }, 59 | "extensions": [ 60 | // python 61 | "ms-python.python", 62 | "ms-python.vscode-pylance", 63 | "ms-python.mypy-type-checker", 64 | "charliermarsh.ruff", 65 | "donjayamanne.python-extension-pack", 66 | // jupyter 67 | "ms-toolsai.jupyter", 68 | "ms-toolsai.jupyter-keymap", 69 | "ms-toolsai.jupyter-renderers", 70 | // git 71 | "mhutchie.git-graph", 72 | "eamodio.gitlens", 73 | "donjayamanne.git-extension-pack", 74 | // markdown 75 | "yzhang.markdown-all-in-one", 76 | "shd101wyy.markdown-preview-enhanced", 77 | "esbenp.prettier-vscode", 78 | // shell 79 | "mads-hartmann.bash-ide-vscode", 80 | "timonwong.shellcheck", 81 | "foxundermoon.shell-format", 82 | // visibility 83 | "mechatroner.rainbow-csv", 84 | "GrapeCity.gc-excelviewer", 85 | "janisdd.vscode-edit-csv", 86 | "monokai.theme-monokai-pro-vscode", 87 | "vscode-icons-team.vscode-icons", 88 | "MS-CEINTL.vscode-language-pack-ja", 89 | // other 90 | "github.copilot", 91 | "github.copilot-chat", 92 | "amazonwebservices.aws-toolkit-vscode", 93 | "amazonwebservices.amazon-q-vscode", 94 | "saoudrizwan.claude-dev" 95 | ] 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /.devcontainer/gpu-sagemaker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM 763104351884.dkr.ecr.ap-northeast-1.amazonaws.com/pytorch-training:2.6.0-gpu-py312-cu126-ubuntu22.04-sagemaker 2 | # FROM 763104351884.dkr.ecr.ap-northeast-1.amazonaws.com/pytorch-training:2.6.0-cpu-py312-ubuntu22.04-sagemaker 3 | # see: https://github.com/aws/deep-learning-containers/blob/master/available_images.md 4 | 5 | COPY ./requirements.txt /tmp/ 6 | 7 | # Install libraries 8 | RUN pip3 install --no-cache-dir -r /tmp/requirements.txt 9 | 10 | # Uninstall awscli v1 and install awscli v2 11 | RUN pip uninstall awscli -y \ 12 | && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ 13 | && unzip awscliv2.zip \ 14 | && ./aws/install \ 15 | && rm -r aws \ 16 | && rm awscliv2.zip 17 | -------------------------------------------------------------------------------- /.devcontainer/gpu-sagemaker/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gpu-sagemaker", // [Optional] Your project name here 3 | "build": { 4 | "dockerfile": "Dockerfile" 5 | }, 6 | "workspaceFolder": "/workspace", 7 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", 8 | "initializeCommand": "bash ${localWorkspaceFolder}/.devcontainer/gpu-sagemaker/init.sh", 9 | "runArgs": [ 10 | "--gpus", 11 | "all", 12 | "--shm-size", 13 | "32g" // shared memory size 14 | ], 15 | "features": { 16 | "ghcr.io/devcontainers/features/common-utils:2": { 17 | "installZsh": false, 18 | "installOhMyZsh": false, 19 | "installOhMyZshConfig": false, 20 | "upgradePackages": false, 21 | "username": "vscode", // Add non-root user 22 | "userUid": "automatic", 23 | "userGid": "automatic" 24 | } 25 | }, 26 | "remoteUser": "vscode", // use non-root user 27 | // Configure tool-specific properties. 28 | "customizations": { 29 | // Configure properties specific to VS Code. 30 | "vscode": { 31 | "settings": { 32 | "terminal.integrated.profiles.linux": { 33 | "bash": { 34 | "path": "/bin/bash" 35 | } 36 | }, 37 | // notebook 38 | "notebook.formatOnSave.enabled": true, 39 | "notebook.codeActionsOnSave": { 40 | "notebook.source.fixAll": "explicit", 41 | "notebook.source.organizeImports": "explicit" 42 | }, 43 | // python 44 | "[python]": { 45 | "editor.formatOnSave": true, 46 | "editor.defaultFormatter": "charliermarsh.ruff", 47 | "editor.codeActionsOnSave": { 48 | "source.fixAll": "explicit", // fix lint violations on-save 49 | "source.organizeImports": "explicit" // organize imports on-save 50 | } 51 | }, 52 | "mypy-type-checker.args": [ 53 | "--config=${workspaceFolder}/pyproject.toml" 54 | ], 55 | "python.defaultInterpreterPath": "/usr/local/bin/python", 56 | "python.analysis.typeCheckingMode": "basic", 57 | "python.analysis.inlayHints.functionReturnTypes": true, 58 | "python.analysis.inlayHints.variableTypes": true, 59 | "python.analysis.completeFunctionParens": true, 60 | // visibility 61 | "editor.bracketPairColorization.enabled": true, 62 | "editor.guides.bracketPairs": "active", 63 | // markdown 64 | "[markdown]": { 65 | "editor.wordWrap": "bounded", 66 | "editor.defaultFormatter": "esbenp.prettier-vscode" 67 | } 68 | }, 69 | "extensions": [ 70 | // python 71 | "ms-python.python", 72 | "ms-python.vscode-pylance", 73 | "ms-python.mypy-type-checker", 74 | "charliermarsh.ruff", 75 | "donjayamanne.python-extension-pack", 76 | // jupyter 77 | "ms-toolsai.jupyter", 78 | "ms-toolsai.jupyter-keymap", 79 | "ms-toolsai.jupyter-renderers", 80 | // git 81 | "mhutchie.git-graph", 82 | "eamodio.gitlens", 83 | "donjayamanne.git-extension-pack", 84 | // markdown 85 | "yzhang.markdown-all-in-one", 86 | "shd101wyy.markdown-preview-enhanced", 87 | "esbenp.prettier-vscode", 88 | // shell 89 | "mads-hartmann.bash-ide-vscode", 90 | "timonwong.shellcheck", 91 | "foxundermoon.shell-format", 92 | // visibility 93 | "mechatroner.rainbow-csv", 94 | "GrapeCity.gc-excelviewer", 95 | "janisdd.vscode-edit-csv", 96 | "monokai.theme-monokai-pro-vscode", 97 | "vscode-icons-team.vscode-icons", 98 | "MS-CEINTL.vscode-language-pack-ja", 99 | // other 100 | "github.copilot", 101 | "github.copilot-chat", 102 | "amazonwebservices.aws-toolkit-vscode", 103 | "amazonwebservices.amazon-q-vscode", 104 | "saoudrizwan.claude-dev" 105 | ] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.devcontainer/gpu-sagemaker/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.ap-northeast-1.amazonaws.com 3 | -------------------------------------------------------------------------------- /.devcontainer/gpu-sagemaker/requirements.txt: -------------------------------------------------------------------------------- 1 | openai==1.76.0 2 | streamlit==1.44.1 3 | -------------------------------------------------------------------------------- /.devcontainer/gpu-uv/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu22.04 2 | 3 | # Install uv by copying the binary from the official distroless Docker image 4 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ 5 | 6 | # Add non-root user 7 | ARG USERNAME=vscode 8 | ARG USER_UID=1000 9 | ARG USER_GID=$USER_UID 10 | 11 | # Install required packages and add non-root user 12 | RUN apt-get update && apt-get install -y \ 13 | curl \ 14 | unzip \ 15 | sudo \ 16 | git \ 17 | && rm -rf /var/lib/apt/lists/* \ 18 | && groupadd --gid $USER_GID $USERNAME \ 19 | && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ 20 | && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ 21 | && chmod 0440 /etc/sudoers.d/$USERNAME 22 | 23 | # Install awscli v2 24 | RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ 25 | && unzip awscliv2.zip \ 26 | && ./aws/install \ 27 | && rm -r aws \ 28 | && rm awscliv2.zip 29 | 30 | # Switch to non-root user 31 | USER $USERNAME 32 | 33 | # Set working directory 34 | WORKDIR /home/$USERNAME/ 35 | -------------------------------------------------------------------------------- /.devcontainer/gpu-uv/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gpu-uv", // [Optional] Your project name here 3 | "build": { 4 | "dockerfile": "Dockerfile" 5 | }, 6 | "workspaceFolder": "/workspace", 7 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", 8 | "mounts": [ 9 | "source=uv-cache,target=/root/.cache/uv,type=volume", // uv cache 10 | "source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,consistency=cached" // git config 11 | ], 12 | "runArgs": [ 13 | "--gpus", 14 | "all", 15 | "--shm-size", 16 | "32g" // shared memory size 17 | ], 18 | "remoteEnv": { 19 | "UV_COMPILE_BYTECODE": "1", 20 | "UV_LINK_MODE": "copy", 21 | "UV_TORCH_BACKEND": "auto" 22 | }, 23 | "postCreateCommand": "uv sync --frozen && . .venv/bin/activate && uv add pre-commit && uv run pre-commit install", 24 | // Configure tool-specific properties. 25 | "customizations": { 26 | // Configure properties specific to VS Code. 27 | "vscode": { 28 | "settings": { 29 | "terminal.integrated.profiles.linux": { 30 | "bash": { 31 | "path": "/bin/bash" 32 | } 33 | }, 34 | // notebook 35 | "notebook.formatOnSave.enabled": true, 36 | "notebook.codeActionsOnSave": { 37 | "notebook.source.fixAll": "explicit", 38 | "notebook.source.organizeImports": "explicit" 39 | }, 40 | // python 41 | "[python]": { 42 | "editor.formatOnSave": true, 43 | "editor.defaultFormatter": "charliermarsh.ruff", 44 | "editor.codeActionsOnSave": { 45 | "source.fixAll": "explicit", // fix lint violations on-save 46 | "source.organizeImports": "explicit" // organize imports on-save 47 | } 48 | }, 49 | "mypy-type-checker.args": [ 50 | "--config=${workspaceFolder}/pyproject.toml" 51 | ], 52 | "python.defaultInterpreterPath": "./.venv/bin/python", 53 | "python.analysis.typeCheckingMode": "basic", 54 | "python.analysis.inlayHints.functionReturnTypes": true, 55 | "python.analysis.inlayHints.variableTypes": true, 56 | "python.analysis.completeFunctionParens": true, 57 | // visibility 58 | "editor.bracketPairColorization.enabled": true, 59 | "editor.guides.bracketPairs": "active", 60 | // markdown 61 | "[markdown]": { 62 | "editor.wordWrap": "bounded", 63 | "editor.defaultFormatter": "esbenp.prettier-vscode" 64 | } 65 | }, 66 | "extensions": [ 67 | // python 68 | "ms-python.python", 69 | "ms-python.vscode-pylance", 70 | "ms-python.mypy-type-checker", 71 | "charliermarsh.ruff", 72 | "donjayamanne.python-extension-pack", 73 | // jupyter 74 | "ms-toolsai.jupyter", 75 | "ms-toolsai.jupyter-keymap", 76 | "ms-toolsai.jupyter-renderers", 77 | // git 78 | "mhutchie.git-graph", 79 | "eamodio.gitlens", 80 | "donjayamanne.git-extension-pack", 81 | // markdown 82 | "yzhang.markdown-all-in-one", 83 | "shd101wyy.markdown-preview-enhanced", 84 | "esbenp.prettier-vscode", 85 | // shell 86 | "mads-hartmann.bash-ide-vscode", 87 | "timonwong.shellcheck", 88 | "foxundermoon.shell-format", 89 | // visibility 90 | "mechatroner.rainbow-csv", 91 | "GrapeCity.gc-excelviewer", 92 | "janisdd.vscode-edit-csv", 93 | "monokai.theme-monokai-pro-vscode", 94 | "vscode-icons-team.vscode-icons", 95 | "MS-CEINTL.vscode-language-pack-ja", 96 | // other 97 | "github.copilot", 98 | "github.copilot-chat", 99 | "amazonwebservices.aws-toolkit-vscode", 100 | "amazonwebservices.amazon-q-vscode", 101 | "saoudrizwan.claude-dev" 102 | ] 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/astral-sh/uv-pre-commit 3 | rev: 0.6.17 4 | hooks: 5 | - id: uv-lock 6 | description: "Ensures that the uv.lock file is up-to-date" 7 | 8 | - repo: https://github.com/astral-sh/ruff-pre-commit 9 | rev: v0.11.7 10 | hooks: 11 | - id: ruff 12 | description: "Runs Ruff for Python code linting and static analysis" 13 | types_or: [python, pyi, jupyter] 14 | args: [--fix, --exit-non-zero-on-fix, --config=pyproject.toml] 15 | - id: ruff-format 16 | description: "Formats Python code using Ruff formatter" 17 | types_or: [python, pyi, jupyter] 18 | args: [--config=pyproject.toml] 19 | 20 | - repo: https://github.com/pre-commit/mirrors-mypy 21 | rev: v1.15.0 22 | hooks: 23 | - id: mypy 24 | description: "Performs type checking using mypy" 25 | types_or: [python, pyi, jupyter] 26 | args: [--config-file=pyproject.toml] 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 Renya Kujirada 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VSCode Dev Containers を利用した AWS EC2 上での開発環境構築手順 2 | 3 | 本リポジトリでは,Windows・Mac・Linux PC 上の Visual Studio Code IDE (VSCode) から AWS EC2 へリモート接続し,VSCode Dev Containers を利用して深層学習や LLM アプリケーション開発を効率良く行えるようにするための手順を示す. 4 | 5 | なお,本リポジトリはチーム開発時に,所属チームへクラウドネイティブで効率的な開発手法を導入することを目的としており,python コーディングにおける linter, formatter や VSCode extension,setting.json なども共通のものを利用するようにしている. 6 | 7 | ## TL;DR 8 | 9 | 以下の Tips を整理し,手順書としてまとめた.また,最小限の手順で済むよう,bat ファイルや shell スクリプトを用意している. 10 | 11 | - AWS Systems Manager (SSM) 経由で VSCode から EC2 にセキュアに SSH 接続する方法 12 | - チーム開発時の IDE として VSCode を利用し,uv,Ruff,mypy を共通的に利用する方法 13 | - AWS Deep Learning Containers Images 等をベースに Dev Containers 上で開発する方法 14 | 15 | ## 目次 16 | 17 | - [背景と課題](#背景と課題) 18 | - [目的](#目的) 19 | - [オリジナリティ](#オリジナリティ) 20 | - [前提](#前提) 21 | - [手順](#手順) 22 | - [手順の各ステップの詳細](#手順の各ステップの詳細) 23 | - [1. AWS CLI のインストールとセットアップ](#1-aws-cli-のインストールとセットアップ) 24 | - [2. SSM Session Manager plugin のインストール](#2-ssm-session-manager-plugin-のインストール) 25 | - [3. ローカルの VSCode に extension をインストール](#3-ローカルの-vscode-に-extension-をインストール) 26 | - [4. CloudFormation で EC2 を構築](#4-cloudformation-で-ec2-を構築) 27 | - [構築するリソース](#構築するリソース) 28 | - [EC2 の仕様について](#ec2-の仕様について) 29 | - [cf テンプレート利用時の入力パラメータについて](#cf-テンプレート利用時の入力パラメータについて) 30 | - [cf テンプレートの簡易説明](#cf-テンプレートの簡易説明) 31 | - [5. SSH の設定](#5-ssh-の設定) 32 | - [6. VSCode から EC2 インスタンスにログイン](#6-vscode-から-ec2-インスタンスにログイン) 33 | - [7. EC2 インスタンスに VSCode extension をインストール](#7-ec2-インスタンスに-vscode-extension-をインストール) 34 | - [8. 新規プロジェクトを作成](#8-新規プロジェクトを作成) 35 | - [9. Dev Containers を利用したコンテナの構築](#9-dev-containers-を利用したコンテナの構築) 36 | - [その他](#その他) 37 | - [インスタンスの起動・停止](#インスタンスの起動停止) 38 | - [コーディングガイドラインと開発環境の設定](#コーディングガイドラインと開発環境の設定) 39 | - [チームでの EC2 の運用・管理](#チームでの-ec2-の運用管理) 40 | - [Tips](#tips) 41 | - [VSCode Extension](#vscode-extension) 42 | - [Dockerfile](#dockerfile) 43 | - [CPU インスタンスで開発する場合](#cpu-インスタンスで開発する場合) 44 | - [CloudFormation Template の UserData の実行ログ](#cloudformation-template-の-userdata-の実行ログ) 45 | - [Ruff が動作しない場合](#ruff-が動作しない場合) 46 | - [Coding Agent の利用](#coding-agent-の利用) 47 | - [参考](#参考) 48 | 49 | ## 背景と課題 50 | 51 | 社内のローカル PC 上で深層学習モデルを開発する際,PoC 毎・メンバ毎に環境構築が必要で,時間を要してしまう課題がある.例えば,NVIDIA drivers や CUDA,PyTorch などのセットアップに苦労し,本来注力すべき本質的な開発タスクに十分なリソースを割くことができない. 52 | 53 | また,LLM API を利用したアプリケーションをチームで開発する際,社内プロキシが原因で開発が非効率になる課題がある.具体的には,API 実行時,SSL 証明書関連のエラーに苦労することが多い.加えて,リモートリポジトリの利用 (git push や pull) が制限されており,コードのバージョン管理や共有ができないことが多い. 54 | 55 | その他,チームの各メンバが利用する開発環境が統一化されていない場合,チームとしての開発効率が低下してしまう課題がある.特に,利用する OS や Python パッケージ管理ツール,Linter,Formatter が異なる場合,コードの一貫性が失われ,レビュープロセスが複雑化する.加え,環境の違いによりメンバ間でのコードの実行結果の再現性が損なわれる. 56 | 57 | AWS Cloud9 や SageMaker AI Studio Code Editor のようなクラウドネイティブ IDE を利用することで,上記の課題を解消できるが,いくつか課題がある.まず,ローカルの VSCode と比較すると,これらのサービスの利用には慣れや経験,知識が必須である.例えば,利用するマシンやそのストレージの実体の把握は,初学者には難しい.次に,ローカルの VSCode で利用可能な Extensions を全て利用できるわけではなく,開発者体験としては高いとは言えない.例えば,[Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) は利用できず,Docker コンテナの利用は CLI コマンド経由でしか行えない.これらの課題により,初学者や新規参画者には敷居が高く,即時参画には時間を要してしまう. 58 | 59 | ## 目的 60 | 61 | ローカル PC 上の VSCode から,VSCode Remote SSH により,SSM Session Manager Plugin 経由で EC2 インスタンスにログインし,EC2 上で開発できるようにする.その際,AWS Deep Learning AMIs を利用する.また,VSCode Dev Containers を利用し,開発環境をコンテナとして統一化する.これにより,開発環境の構築を自動化し,メンバ間でのコードの実行結果の再現性を担保する.また,社内プロキシ起因の課題を回避し,CodeCommit などのセキュアなリポジトリサービスを利用することができる. 62 | 63 | また,チーム開発で利用する IDE として VSCode を利用し,Python パッケージ管理ツール,Linter,Formatter,Extensions を統一化する.これにより,チームとしてのコーディングスタイルの統一化,コードの可動性や一貫性の向上を狙う.また,VSCode の Extensions である Dev Containers や Git Graph を利用することで,初学者には敷居の高い docker コマンドや git コマンドを利用せず,容易にコンテナ上での開発や,GUI ベースの Git 運用を行えるようにする. 64 | 65 | 66 | 67 | ## オリジナリティ 68 | 69 | 深層学習モデル開発,LLM API を利用したアプリケーション開発,SageMaker Pipelines 開発など,用途別に Dev Containers の環境を用意している.これらの環境では,基本的には Python パッケージ管理には uv,Formatter や Linter には Ruff を利用しており,git や aws cli が利用可能である.加え,Dev Containers を利用しているので Cline や Amazon Q Developer などの VSCode Extensions をコンテナ内でセキュアに利用することが可能である. 70 | 71 | | コンテナ名 | 用途 | 特徴 | 72 | | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 73 | | [cpu-uv](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/cpu-uv) | LLM API を利用したアプリケーション開発を想定 | - 軽量な Docker イメージを利用
- uv や Ruff を利用可能 | 74 | | [gpu-uv](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/gpu-uv) | 深層学習モデル開発 | - CUDA や cuDNN がセットアップ済み
- uv や Ruff を利用可能 | 75 | | [gpu-sagemaker](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/gpu-sagemaker) | SageMaker Pipeline の開発や Training Job の実行 | - [AWS Deep Learning Containers Images](https://github.com/aws/deep-learning-containers/blob/master/available_images.md) を利用
- PyTorch がプリインストール済み (pip) | 76 | 77 | ## 前提 78 | 79 | Windows,Linux 上には VSCode は install されているものとする.加え,AWS ユーザーは作成済みであり,以下のポリシーで定義される権限を最低限付与していることを想定している.なお,手順書中では,Windows でのセットアップに主眼を起き記述している.(Linux でも同様の手順で実施可能.) 80 | 81 |
82 | 最低限必要なポリシー 83 |
84 | 85 | ```json 86 | { 87 | "Version": "2012-10-17", 88 | "Statement": [ 89 | { 90 | "Sid": "EC2InstanceManagement", 91 | "Effect": "Allow", 92 | "Action": ["ec2:StartInstances", "ec2:StopInstances"], 93 | "Resource": "arn:aws:ec2:*:*:instance/*" 94 | }, 95 | { 96 | "Sid": "EC2DescribeAccess", 97 | "Effect": "Allow", 98 | "Action": "ec2:DescribeInstances", 99 | "Resource": "*" 100 | }, 101 | { 102 | "Sid": "SSMSessionAccess", 103 | "Effect": "Allow", 104 | "Action": "ssm:StartSession", 105 | "Resource": [ 106 | "arn:aws:ssm:*:*:document/AWS-StartSSHSession", 107 | "arn:aws:ec2:*:*:instance/*" 108 | ] 109 | }, 110 | { 111 | "Sid": "SSMParameterAccess", 112 | "Effect": "Allow", 113 | "Action": "ssm:GetParameter", 114 | "Resource": "arn:aws:ssm:*:*:parameter/ec2/keypair/*" 115 | } 116 | ] 117 | } 118 | ``` 119 | 120 |
121 |
122 | 123 | ## 手順 124 | 125 | 1. AWS CLI のインストールとセットアップ 126 | 2. SSM Session Manager plugin のインストール 127 | 3. ローカルの VSCode に extension をインストール 128 | 4. CloudFormation で EC2 を構築 129 | 5. SSH の設定 130 | 6. VSCode から EC2 インスタンスにログイン 131 | 7. EC2 インスタンスに VSCode extension をインストール 132 | 8. 新規プロジェクトを作成 133 | 9. Dev Containers を利用したコンテナの構築 134 | 135 | ## 手順の各ステップの詳細 136 | 137 | ### 1. AWS CLI のインストールとセットアップ 138 | 139 | 公式ドキュメント[^1-1] [^1-2]を参考に,AWS CLI をインストール,セットアップする. 140 | 141 | - [Windows 用の AWS CLI MSI インストーラ (64 ビット)](https://awscli.amazonaws.com/AWSCLIV2.msi) をダウンロードして実行する 142 | - インストール後,`aws --version`でバージョンが表示されれば OK 143 | - `aws configure`を実行し,AWS CLI の設定を行う 144 | 145 | ``` 146 | AWS Access Key ID [None]: IAM ユーザーの作成時にダウンロードした csv ファイルに記載 147 | AWS Secret Access Key [None]: IAM ユーザーの作成時にダウンロードした csv ファイルに記載 148 | Default region name [None]: ap-northeast-1 149 | Default output format [None]: json 150 | ``` 151 | 152 | - Zscaler などの社内プロキシを利用している場合は,`.aws/config`に以下を追記する.例えば,Zscaler を利用している場合は,以下のように CA 証明書のフルパスを記述する.CA 証明書のエクスポート方法は後述するので,必要があれば適宜参照されたい. 153 | 154 | ``` 155 | ca_bundle = C:\path\to\zscalar_root_cacert.cer 156 | ``` 157 | 158 |
159 | ※Zscaler CA 証明書のエクスポート方法 160 |
161 | 162 | Zscaler を利用してプロキシエージェント経由で通信を行う場合,Zscaler では SSL インスペクションの設定がなされているため,https 通信を行うときにルート証明書の情報が Zscaler のものに上書きされる.そのため,Zscaler のルート証明書を実行環境の証明書の信頼リストに登録しなければ https 通信が失敗する場合がある. 163 | 164 | **Windows の場合** 165 | 166 | 公式ドキュメント[^1-3]を参考に,Zscaler のルート証明書をエクスポートする. 167 | 168 | - コンピュータ証明書の管理 > 信頼されたルート証明機関 > 証明書 169 | - Zscalar Root CA を左クリック > すべてのタスク > エクスポート 170 | - 証明書のエクスポートウィザードで,次へ > Base 64 encoded X.509 を選択して次へ 171 | - 参照 > ディレクトリ・ファイル名を入力(ここではファイル名を`zscalar_root_cacert.cer`とする)> 次へ > 完了 > OK 172 | 173 | **macOS の場合** 174 | 175 | - Keychain を開き,システムチェーン -> システム の中にある Zscaler Root CA を右クリック 176 | - 「"Zscaler Root CA"を書き出す...」 を選択 177 | - `/path/to/zscalar_root_cacert.cer`などのファイル名で,任意のパスに保存 178 | 179 |
180 |
181 | 182 | ### 2. SSM Session Manager plugin のインストール 183 | 184 | 公式ドキュメント[^2-1]を参考に,SSM Session Manager plugin をインストールする. 185 | 186 | - [Session Manager プラグインのインストーラ](https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows/SessionManagerPluginSetup.exe)をダウンロードし実行する 187 | 188 | ### 3. ローカルの VSCode に extension をインストール 189 | 190 | [`./setup/vscode/vscode_local_setup_win.bat`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/vscode/vscode_local_setup_win.bat)を実行し,VSCode の extension を一括インストールする.Linux の場合は,[`./setup/vscode/vscode_local_setup_linux.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/vscode/vscode_local_setup_linux.sh)を実行する.本バッチファイル,または shell の実行により,以下の extension がインストールされる. 191 | 192 | - vscode-remote-extensionpack: VSCode でリモート開発を行うための extension 193 | - aws-toolkit-vscode: AWS の各種サービスを VSCode から操作するための extension 194 | - ec2-farm: AWS アカウント内の EC2 インスタンスの状態を確認し,起動・停止・再起動を行うための extension 195 | 196 | ### 4. CloudFormation で EC2 を構築 197 | 198 | [`./setup/cf-template/cf-ec2.yaml`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/cf-template/cf-ec2.yaml)(cf テンプレート)を利用し,CloudFormation で EC2 を構築する.以下に実際に構築されるリソースと,cf テンプレートの簡易説明を行う.また,CloudFormation の詳細な実行方法は後述しているので,必要があれば適宜参照されたい. 199 | 200 | #### 構築するリソース 201 | 202 | - EC2 203 | - EC2 Key pair 204 | - Security Group 205 | 206 | 207 | 208 | #### EC2 の仕様について 209 | 210 | Deep Learning 用の AMI を利用しているため,以下が全てインストールされている状態で EC2 が構築される.詳細な仕様は,本 AWS ドキュメント[^4-1] [^4-2]を参照されたい. 211 | 212 | - Git 213 | - AWS CLI (v2 は `aws2`,v1 は `aws` コマンド) 214 | - Python (3.11) 215 | - Docker 216 | - NVIDIA Container Toolkit 217 | - NVIDIA driver (570.86.15) 218 | - CUDA, cuDNN (12.6) 219 | - PyTorch (2.6) 220 | - uv 221 | 222 | #### cf テンプレート利用時の入力パラメータについて 223 | 224 | | パラメータ名 | 説明 | デフォルト値 | 225 | | ----------------- | ------------------------------------- | ----------------------------------------------------------------------------- | 226 | | `EC2InstanceType` | 利用する EC2 のインスタンスタイプ | `g4dn.xlarge` (GPU インスタンス),`m5.large`などの CPU インスタンスも設定可能 | 227 | | `ImageId` | 利用する EC2 の AMI の種類 | `Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.6 (Ubuntu 22.04)` | 228 | | `SubnetId` | インターネット接続可能なサブネット ID | 指定必須(不明な場合は default VPC のパブリックサブネットを利用) | 229 | | `VolumeSize` | EC2 のボリュームサイズ | 100GB | 230 | | `VPCId` | 利用するサブネットが属する VPC の ID | 指定必須(不明な場合は default VPC を利用) | 231 | 232 | #### cf テンプレートの簡易説明 233 | 234 | - EC2 へのリモートアクセス・開発に必要と想定されるポリシーをアタッチしたロールは自動作成される.以下のポリシーをアタッチしている. 235 | - AmazonSSMManagedInstanceCore 236 | - AmazonS3FullAccess 237 | - AWSCodeCommitFullAccess 238 | - EC2InstanceProfileForImageBuilderECRContainerBuilds 239 | - AmazonSageMakerFullAccess 240 | - SecretsManagerReadWrite 241 | - AWSLambda_FullAccess 242 | - AmazonBedrockFullAccess 243 | - AmazonECS_FullAccess 244 | - セキュリティグループも自動作成しており,インバウンドは全てシャットアウトしている 245 | - SSH 接続で利用する Key Pair を作成している 246 | - EC2 インスタンス作成時,以下を自動実行している 247 | - git のアップグレード 248 | - uv のインストール 249 | - venv の仮想環境の activate 250 | - CloudFormation の出力部には,インスタンス ID と Key ID を出力している 251 | - 後述の shell で利用する 252 | 253 |
254 | ※CloudFormation 実行手順 255 |
256 | 257 | - [CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)を開き,スタックの作成を押下 258 | - テンプレートの指定 > テンプレートファイルのアップロード > ファイルの選択で上記で作成した yaml ファイルを指定し,次へを押下 259 | - [`./setup/cf-template/cf-ec2.yaml`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/cf-template/cf-ec2.yaml)を upload する 260 | - 任意の事情で upload が出来ない場合,テンプレートを S3 経由で利用するか,Application Composer を利用してテンプレートを利用すると良い (ローカル PC 上 or CloudShell 上で,cf テンプレートを S3 にアップロードする必要がある) 261 | - 任意のスタック名(利用者名などでよい)を入力後,以下のパラメータを設定・変更する 262 | - EC2InstanceType: インスタンスタイプ.デフォルトは g4dn.xlarge 263 | - ImageId: AMI の ID.デフォルトは Deep Learning AMI GPU PyTorch の ID 264 | - SubnetID: 利用するパブリックサブネットの ID(デフォルト VPC のパブリックサブネット ID 等で問題ない) 265 | - VPCId: 利用する VPC の ID(デフォルト VPC の ID 等で問題ない) 266 | - VolumeSize: ボリュームサイズ.デフォルトは 100GB 267 | - 適切な IAM Role をアタッチし,次へを押下(一時的に AdministratorAccess を付与したロールを利用しても良い) 268 | - 作成されるまで 5 分ほど待つ 269 | 270 |
271 |
272 | 273 | ### 5. SSH の設定 274 | 275 | [`./setup/get_aws_keypair/get_key_win.bat`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/ssh/ssh_setup_win.bat)を実行し,秘密鍵のダウンロードと`.ssh/config`の設定を自動実行する.Linux の場合は[`./setup/get_aws_keypair/get_key_linux.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/ssh/ssh_setup_linux.sh)を実行すること.なお,実行前に,ソースコードの変数`KEY_ID`と`INSTANCE_ID`には CloudFormation の実行結果の各値を記述すること.また,複数台の EC2 を利用する場合,変数`HOST`や`SECRET_KEY`は一意になるように設定すること. 276 | 277 | ### 6. VSCode から EC2 インスタンスにログイン 278 | 279 | VSCode のリモート接続機能を利用して,SSM Session Manager Plugin 経由で EC2 インスタンスに SSH でログインする.以下,CloudFormation により EC2 の構築が完了している前提で説明する. 280 | 281 | - VSCode 上で,`F1`を押下し,`Remote-SSH: Connect to Host...`を選択 282 | - `~/.ssh/config`に記述したホスト名を選択(デフォルトでは`ec2`となっている) 283 | - Select the platform of the remtoe host "ec2" という画面が出たら`Linux`を選択すること 284 | - ※スタックの作成が完了しても,cf テンプレート内の UserData の shell 実行が終わるまで待つ必要があるため注意.(CloudFormation の実行完了後, 2, 3 分程度待つこと.UserData の実行ログは`/var/log/cloud-init-output.log`で確認できる.) 285 | - EC2 インスタンスにログイン後,インスタンス上に本リポジトリを clone する. 286 | - [`./setup/check_vm_env/check_cuda_torch.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/check_vm_env/check_cuda_torch.sh)を実行し,EC2 インスタンス上で GPU や pytorch が利用可能であることを確認する.以下のような出力が表示されるはずである. 287 | - PyTorch を利用した MNIST の画像分類の学習を行うスクリプト[`./setup/check_vm_env/mnist_example/mnist.py`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/check_vm_env/mnist_example/mnist.py)を用意しているため,これを実行しても構わない. 288 | 289 | ``` 290 | ==============check cuda============== 291 | nvcc: NVIDIA (R) Cuda compiler driver 292 | Copyright (c) 2005-2024 NVIDIA Corporation 293 | Built on Tue_Oct_29_23:50:19_PDT_2024 294 | Cuda compilation tools, release 12.6, V12.6.85 295 | Build cuda_12.6.r12.6/compiler.35059454_0 296 | ==============check gpu============== 297 | Sun Apr 27 04:59:53 2025 298 | +-----------------------------------------------------------------------------------------+ 299 | | NVIDIA-SMI 570.86.15 Driver Version: 570.86.15 CUDA Version: 12.8 | 300 | |-----------------------------------------+------------------------+----------------------+ 301 | | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | 302 | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | 303 | | | | MIG M. | 304 | |=========================================+========================+======================| 305 | | 0 Tesla T4 On | 00000000:00:1E.0 Off | 0 | 306 | | N/A 26C P8 9W / 70W | 1MiB / 15360MiB | 0% Default | 307 | | | | N/A | 308 | +-----------------------------------------+------------------------+----------------------+ 309 | 310 | +-----------------------------------------------------------------------------------------+ 311 | | Processes: | 312 | | GPU GI CI PID Type Process name GPU Memory | 313 | | ID ID Usage | 314 | |=========================================================================================| 315 | | No running processes found | 316 | +-----------------------------------------------------------------------------------------+ 317 | ==============check torch============== 318 | if you exec at first time, you might wait for a while... 319 | torch.__version__: 2.6.0+cu126 320 | torch.cuda.is_available(): True 321 | ``` 322 | 323 | ### 7. EC2 インスタンスに VSCode extension をインストール 324 | 325 | [`./setup/vscode/vscode_vm_setup.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/vscode/vscode_vm_setup.sh)を実行し,EC2 インスタンス上で Git の初期設定と VSCode extension のインストール,VSCode の setting.json の設定を行う.なお,shell 実行時,Git の設定で利用する名前とメールアドレスをコマンドから入力すること. 326 | 327 | ### 8. 新規プロジェクトを作成 328 | 329 | [`./setup/make_new_project.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/make_new_project.sh)を実行し,新規プロジェクトを作成する.新規プロジェクトは,本リポジトリ(テンプレート)を基に作成され,本リポジトリの一つ上の階層に作成される. 330 | 331 | `./setup/make_new_project.sh`を実行すると,プロジェクト名と,利用するコンテナ環境を選択するように求められる.プロジェクト名は任意の名前を入力すること.入力したプロジェクト名のディレクトリが新規プロジェクトとして作成される.また,コンテナ環境は,以下の 3 つから用途別に選択すること.各コンテナの詳細は後述する. 332 | 333 | - [cpu-uv](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/cpu-uv): LLM API を利用したアプリケーション開発を想定. 334 | - [gpu-uv](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/gpu-uv): GPU を利用した深層学習モデル開発を想定. 335 | - [gpu-sagemaker](https://github.com/ren8k/aws-ec2-devkit-vscode/tree/main/.devcontainer/gpu-sagemaker): SageMaker Pipeline の開発や SageMaker Training Job の実行を想定. 336 | 337 | `./setup/make_new_project.sh`の実行後,作成される新規プロジェクトは以下のようなディレクトリ構成となる.なお,以下では,入力したプロジェクト名を`sample-project`と仮定している. 338 | 339 | ``` 340 | sample-project/ 341 | ├── .devcontainer/ # 選択したDocker環境(cpu-uv、gpu-uv、gpu-sagemaker)の.devcontainerのみをコピー 342 | │ ├── Dockerfile 343 | │ └── devcontainer.json # プロジェクト名が設定済み 344 | ├── .git/ # Gitリポジトリ(初期化済み) 345 | ├── .gitignore 346 | ├── .pre-commit-config.yaml 347 | ├── README.md # プロジェクト名がタイトルに設定 348 | ├── pyproject.toml # プロジェクト名が設定済み 349 | ├── src/ 350 | │ ├── __init__.py 351 | │ └── main.py 352 | └── uv.lock # プロジェクト名が設定済み 353 | ``` 354 | 355 | `./setup/make_new_project.sh`の出力に従い,プロジェクトディレクトリに移動し,VSCode でディレクトリを開く.以下に出力の例を示す. 356 | 357 | ``` 358 | [INFO] 次のステップ: 359 | 1. cd /path/to/sample-project 360 | 2. VS Code でディレクトリを開く 361 | 3. Dev Container でコンテナを起動する 362 | 4. 開発を開始! 363 | ``` 364 | 365 | 参考に,各コンテナの説明を行う. 366 | 367 |
368 | cpu-uv 369 |
370 | 371 | - Python パッケージ管理には uv,Linter や Formatter には Ruff を利用している. 372 | - uv の基本的な利用方法は後述するが,詳細な利用方法は,公式ドキュメント [^8-1] や 技術ブログ [^8-2] [^8-3] を参照されたい. 373 | - Dockerfile 内部では,sudo を利用可能な一般ユーザーの作成および, AWS CLI v2 のインストールを行っている. 374 | - `uv add <パッケージ名>` でパッケージを install 可能. 375 | - `uv remove <パッケージ名>` でパッケージを uninstall 可能. 376 | - Python のバージョンを変更したい場合,`pyproject.toml`の`requires-python`を任意のバージョンに変更した後,`uv python pin <バージョン>` ,`uv sync`を実行する. 377 | - Ex. Python 3.11 を利用したい場合: `pyproject.toml`の`requires-python`を`">=3.11"`に変更し,`uv python pin 3.11 && uv sync`を実行する. 378 | - `uv run python`コマンド,または,venv の仮想環境を activate した状態で`python`コマンドを利用して,Python コードを実行可能. 379 | - 仮想環境の activate は`. .venv/bin/activate`コマンドで可能 380 | - pre-commit を利用し Git コミットする直前に Ruff や mypy による Lint,Format,型のチェックを行っている. 381 | 382 |
383 |
384 | 385 |
386 | gpu-uv 387 |
388 | 389 | - Python パッケージ管理には uv,Linter や Formatter には Ruff を利用している. 390 | - uv の基本的な利用方法は後述するが,詳細な利用方法は,公式ドキュメント [^8-1] や 技術ブログ [^8-2] [^8-3] を参照されたい. 391 | - Dockerfile 内部では,sudo を利用可能な一般ユーザーの作成および, AWS CLI v2 のインストールを行っている. 392 | - `uv add <パッケージ名>` でパッケージを install 可能. 393 | - `uv remove <パッケージ名>` でパッケージを uninstall 可能. 394 | - Python のバージョンを変更したい場合,`pyproject.toml`の`requires-python`を任意のバージョンに変更した後,`uv python pin <バージョン>` ,`uv sync`を実行する. 395 | - Ex. Python 3.11 を利用したい場合: `pyproject.toml`の`requires-python`を`">=3.11"`に変更し,`uv python pin 3.11 && uv sync`を実行する. 396 | - `uv run python`コマンド,または,venv の仮想環境を activate した状態で`python`コマンドを利用して,Python コードを実行可能. 397 | - 仮想環境の activate は`. .venv/bin/activate`コマンドで可能 398 | - PyTorch を install する場合,[`uv add torch torchvision`](https://docs.astral.sh/uv/guides/install-python/) を実行する. 399 | - pre-commit を利用し Git コミットする直前に Ruff や mypy による Lint,Format,型のチェックを行っている. 400 | - CUDA のバージョンは以下. 401 | 402 | ``` 403 | $ nvcc -V 404 | nvcc: NVIDIA (R) Cuda compiler driver 405 | Copyright (c) 2005-2025 NVIDIA Corporation 406 | Built on Fri_Feb_21_20:23:50_PST_2025 407 | Cuda compilation tools, release 12.8, V12.8.93 408 | Build cuda_12.8.r12.8/compiler.35583870_0 409 | ``` 410 | 411 |
412 |
413 | 414 |
415 | gpu-sagemaker 416 |
417 | 418 | - [AWS Deep Learning Containers Images](https://github.com/aws/deep-learning-containers/blob/master/available_images.md)を利用し,コンテナを構築している.[AWS Deep Learning Containers Images](https://github.com/aws/deep-learning-containers/blob/master/available_images.md)は,PyTorch, Tensorflow, MXNet などのフレームワークがプリインストールされたイメージ(SageMaker Training Job での実行環境イメージ)に加え,HuggingFace,StabilityAI のモデルの推論のためのイメージが提供されており,利用するイメージを適宜変更・カスタマイズすることで検証時の環境構築を効率化することができる. 419 | - Python パッケージ管理には pip,Linter や Formatter には Ruff を利用している.pip を利用している理由は,本 Docker イメージで pip 経由でプリインストールされている PyTorch などをクイックに利用することを想定しているためである. 420 | - Dockerfile 内部では, AWS CLI v2 のインストールを行っている. 421 | - devcontainer.json では以下の処理を行っている. 422 | - `initializeCommand`で, ECR へのログイン 423 | - `features`で,non-root ユーザーの作成 424 | - `remote`で,コンテナにおけるプロセス実行ユーザーを指定 425 | - [`./setup/check_vm_env/check_cuda_torch.sh`](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/setup/check_vm_env/check_cuda_torch.sh)を実行し,コンテナ内で GPU や PyTorch が利用可能であることを確認する. 426 | 427 | ``` 428 | ==============check cuda============== 429 | nvcc: NVIDIA (R) Cuda compiler driver 430 | Copyright (c) 2005-2024 NVIDIA Corporation 431 | Built on Tue_Oct_29_23:50:19_PDT_2024 432 | Cuda compilation tools, release 12.6, V12.6.85 433 | Build cuda_12.6.r12.6/compiler.35059454_0 434 | ==============check gpu============== 435 | Sun Apr 27 04:57:38 2025 436 | +-----------------------------------------------------------------------------------------+ 437 | | NVIDIA-SMI 570.86.15 Driver Version: 570.86.15 CUDA Version: 12.8 | 438 | |-----------------------------------------+------------------------+----------------------+ 439 | | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | 440 | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | 441 | | | | MIG M. | 442 | |=========================================+========================+======================| 443 | | 0 Tesla T4 On | 00000000:00:1E.0 Off | 0 | 444 | | N/A 29C P8 13W / 70W | 1MiB / 15360MiB | 0% Default | 445 | | | | N/A | 446 | +-----------------------------------------+------------------------+----------------------+ 447 | 448 | +-----------------------------------------------------------------------------------------+ 449 | | Processes: | 450 | | GPU GI CI PID Type Process name GPU Memory | 451 | | ID ID Usage | 452 | |=========================================================================================| 453 | | No running processes found | 454 | +-----------------------------------------------------------------------------------------+ 455 | ==============check torch============== 456 | if you exec at first time, you might wait for a while... 457 | torch.__version__: 2.6.0+cu126 458 | torch.cuda.is_available(): True 459 | ``` 460 | 461 |
462 |
463 | 464 | ### 9. Dev Containers を利用したコンテナの構築 465 | 466 | Dev Containers を利用することで,GUI でコンテナを起動し,コンテナ内で容易に開発することができる. 467 | 468 | - VSCode 上で`F1`を押下し,`Dev Container: Reopen in Container`を選択する. 469 | - 初回のコンテナ構築時は,Docker イメージの pull に時間がかかるため,3~5 分程度待つ. 470 | 471 | 以下に利用時の注意点を示す. 472 | 473 | - コンテナ内での作業ディレクトリは`/workspace`であり,ローカルのプロジェクトディレクトリがマウントされている. 474 | - コンテナ内での作業ユーザー名は`vscode`であり,sudo 権限を持つ. 475 | - `devcontainer.json`の 2 行目の`name`には,手順 8 で入力したプロジェクト名が設定されている. 476 | - コンテナ構築後,remote repository の登録を行うこと. 477 | - VSCode 上で`F1`を押下し,`Git: Add Remote`を選択する. 478 | - リモートリポジトリの URL を入力する. (CodeCommit の https URL など) 479 | - リモート名を入力する.(`origin`などで良い) 480 | - リモートリポジトリの登録後,VSCode の左側の Git アイコンをクリックし,コミットやプッシュなどの操作が可能になる. 481 | 482 | ## その他 483 | 484 | ### インスタンスの起動・停止 485 | 486 | 開発開始時・終了時には,VSCode extension `EC2 Farm`経由で各々の EC2 インスタンスを起動・停止することが可能である.(AWS コンソールを開く必要はない.) 487 | 488 | ### コーディングガイドラインと開発環境の設定 489 | 490 | チーム開発において VSCode を利用するメリットは,Linter や Formatter をチームで共通化できる上,IDE の設定や利用する extension なども共通化することができる点である.これにより,チームメンバ間での利用するツールやコーディング上の認識齟齬は低減され,利便性の高い extension によって開発効率が向上する.また,pre-commit を利用し Git コミットする直前に Ruff や mypy による Lint,Format,型のチェックを行っている.詳細は,[./docs/coding-guidelines.md](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/docs/coding-guidelines.md)を参照されたい. 491 | 492 | ### チームでの EC2 の運用・管理 493 | 494 | インスタンスの切り忘れ防止のために,AWS Lambda を利用して,夜 12 時に全ての EC2 インスタンスを停止している.なお,運用サーバーなど特定のインスタンスは除外可能にできるようにしている.詳細は,[./docs/operation_ec2.md](https://github.com/Renya-Kujirada/aws-ec2-devkit-vscode/blob/main/docs/operation_ec2.md)を参照されたい. 495 | 496 | ### Tips 497 | 498 | #### VSCode Extension 499 | 500 | - Git 運用は,`Git Graph` を利用することで,GUI で行うことができる. 501 | - Docker コンテナ運用は,`Dev Containers` を利用することで,GUI で行うことができる. 502 | - EC2 インスタンスの起動や停止は,ローカルの VSCode にインストールした extension の`ec2-farm`で行える. 503 | - `ec2-farm`を開き,右クリックで EC2 を起動 or 停止が可能 504 | - リモートの Dev Container 環境への接続は,ローカルの VSCode にインストールした extension の`Project Manager`で行える. 505 | - Project Manager に登録したい Dev Container 環境を VSCode で起動 506 | - `Project Manager`を開き,Save Project (小さいディスクのアイコン) を選択し,Dev Container 環境を登録(任意の名前で保存可能) 507 | - 次回以降は,`ec2-farm`で EC2 を起動後,`Project Manager`に表示された Dev Container 名を選択することで,ssh 接続および Dev Container 起動と接続までが一度に実行可能 508 | 509 | #### Dockerfile 510 | 511 | - gpu-sagemaker において,Dockerfile の 1 行目で指定しているイメージを適宜変更することで,利用するモデルに応じた環境を容易に構築することができる. 512 | - ECR で利用可能なイメージは,[本リンク](https://github.com/aws/deep-learning-containers/blob/master/available_images.md)を参照されたい. 513 | - 例えば,Stable Diffusion 系列のモデルや,Stable Diffusion Web UI などを実行したい場合などは,以下のイメージを指定することで,簡単に環境を構築することができる. 514 | - `763104351884.dkr.ecr.ap-northeast-1.amazonaws.com/stabilityai-pytorch-inference:2.0.1-sgm0.1.0-gpu-py310-cu118-ubuntu20.04-sagemaker` 515 | - イメージによっては,non-root user が定義されている可能性がある.その場合,Dockerfile の 12~27 行目はコメントアウトすること(Dockerfile 内では明示的に non-root user を作成している) 516 | - non-root user を作成する際,Dockerfile ではなく,[`devcontainer.json`](https://github.com/ren8k/aws-ec2-devkit-vscode/blob/main/.devcontainer/gpu-sagemaker/devcontainer.json) の `features`の `common-utils` や`remoteUser`で設定することも可能である.詳細や使用例は,公式ドキュメント[^10-1]や公式リポジトリ[^10-2],技術ブログ[^10-3]を参照されたい. 517 | - gpu-sagemaker の [devcontainer.json](https://github.com/ren8k/aws-ec2-devkit-vscode/blob/main/.devcontainer/gpu-sagemaker/devcontainer.json) では,上記の方法で non-root user を作成している. 518 | 519 | #### CPU インスタンスで開発する場合 520 | 521 | - EC2 インスタンスのインスタンスタイプを,`m5.xlarge`などに変更する 522 | - 利用している AMI では GPU インスタンス以外は非推奨だが,問題なく動作した 523 | - gpu-sagemaker を利用する場合,`.devcontainer/devcontainer.json`の 9 行目と 14 行目をコメントアウトする 524 | - docker コマンドの引数`--gpus all`を除外する 525 | - コンテナのリビルドを実行する 526 | 527 | #### CloudFormation Template の UserData の実行ログ 528 | 529 | - EC2 インスタンスの以下のパスにログが出力される 530 | - `/var/log/cloud-init-output.log` 531 | 532 | #### Ruff が動作しない場合 533 | 534 | - VSCode 上で`F1`を押下し,`Python: Select Interpreter`を選択し,利用する Python のパスが適切に設定されているかを確認する. 535 | 536 | #### Coding Agent の利用 537 | 538 | - [`./setup/coding_agent`](https://github.com/ren8k/aws-ec2-devkit-vscode/blob/main/setup/coding_agent)ディレクトリでは,EC2 で Claude Code や Cline の設定を行うためのファイルを用意している. 539 | 540 | ## 参考 541 | 542 | [^1-1]: [AWS CLI の最新バージョンを使用してインストールまたは更新を行う](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html) 543 | [^1-2]: [AWS CLI をセットアップする](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-quickstart.html) 544 | [^1-3]: [CA 証明書のエクスポート](https://help.zscaler.com/ja/deception/exporting-root-ca-certificate-active-directory-certificate-service) 545 | [^2-1]: [Windows での Session Manager プラグインのインストール](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/install-plugin-windows.html) 546 | [^4-1]: [AWS Deep Learning AMI GPU PyTorch 2.6 (Ubuntu 22.04)](https://aws.amazon.com/jp/releasenotes/aws-deep-learning-ami-gpu-pytorch-2-6-ubuntu-22-04/) 547 | [^4-2]: [AWS Deep Learning AMIs](https://docs.aws.amazon.com/ja_jp/dlami/latest/devguide/dlami-dg.pdf) 548 | [^8-1]: [uv: Managing dependencies](https://docs.astral.sh/uv/concepts/projects/dependencies/) 549 | [^8-2]: [uv だけで Python プロジェクトを管理する](https://zenn.dev/turing_motors/articles/594fbef42a36ee) 550 | [^8-3]: [uv から始まる Python 開発環境構築](https://zenn.dev/dena/articles/python_env_with_uv) 551 | [^10-1]: [Add a non-root user to a container](https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user) 552 | [^10-2]: [github repository: devcontainers / features](https://github.com/devcontainers/features/tree/main/src/common-utils) 553 | [^10-3]: [devcontainer で X11 forwarding 可能な環境を作る (あと uv と CUDA 環境も構築)](https://zenn.dev/colum2131/articles/c8b053b84ade7f) 554 | -------------------------------------------------------------------------------- /docs/coding-guidelines.md: -------------------------------------------------------------------------------- 1 | # コーディングガイドラインと開発環境の設定 2 | 3 | VSCode を利用すれば,チーム内で Linter と Formatter の設定などを容易に統一することができる.特に,複数のエンジニアによるチーム開発において,リポジトリ内部でコーディングの一貫性を保つことは,可動性や品質の向上,チームメンバー間のコミュニケーション円滑化(認識・解釈齟齬の低下),引き継ぎ工数の削減の観点で重要である. 4 | 5 | 本リポジトリでは,上記を実現するために,Dev Containers 内で以下のツール・設定ファイルの共通利用を前提としている.なお,`./.devcontainer/devcontainer.json`ではデフォルトで以下を利用するための設定が記述されている. 6 | 7 | - Python package manager 8 | - Linter 9 | - Formatter 10 | - Type Hints 11 | - pre-commit 12 | - VSCode Extensions 13 | - settings.json 14 | 15 | ## Python package manager 16 | 17 | Python package manager は,Python ライブラリやパッケージのインストール,バージョン管理,依存関係の管理を行うためのツールである.本リポジトリでは,[uv](https://docs.astral.sh/uv/) を利用している.uv は,Rust で実装された Python のバージョンおよび Python パッケージを管理できるツールであり,pipenv や conda などの既存のツールと比べ,高速に実行できる. 18 | 19 | ## Linter 20 | 21 | Linter は,ソースコードを分析し,構文エラーやコーディングスタイルの問題,バグの可能性がある箇所を特定するツールである.本リポジトリでは,Python の Linter として [Ruff](https://docs.astral.sh/ruff/) を利用している.Ruff は,Rust で実装された Linter 兼 Formatte であり,Flake8 などの既存の Linter と比べ高速に実行できる. 22 | 23 | ## Formatter 24 | 25 | Formatter は,ソースコードのフォーマットを整理し,一貫したスタイルでコードを自動整形するツールである.本リポジトリでは,Python の Formatter として [Ruff](https://docs.astral.sh/ruff/) を利用している. 26 | 27 | ## Type Hints 28 | 29 | Type Hints は,特に静的型付け言語において,変数や関数の戻り値の型を指定するための構文である.本リポジトリでは,Python の Type Hints のチェックツールとして [mypy](https://mypy.readthedocs.io/en/stable/) を利用している.mypy は型アノテーションに基づきコードのバグを検知するツールである. 30 | 31 | ## pre-commit 32 | 33 | pre-commit は,Git のコミット前に自動的にコードのフォーマットや Lint チェックを実行するためのツールである.本リポジトリでは,以下の .pre-commit-config.yaml を利用し,以下の内容を実行している. 34 | 35 | - uv lock ファイルが更新されているか 36 | - Ruff による Lint,Format チェック 37 | - mypy による Type チェック 38 | 39 | ```yaml 40 | repos: 41 | - repo: https://github.com/astral-sh/uv-pre-commit 42 | rev: 0.6.17 43 | hooks: 44 | - id: uv-lock 45 | description: "Ensures that the uv.lock file is up-to-date" 46 | 47 | - repo: https://github.com/astral-sh/ruff-pre-commit 48 | rev: v0.11.7 49 | hooks: 50 | - id: ruff 51 | description: "Runs Ruff for Python code linting and static analysis" 52 | types_or: [python, pyi, jupyter] 53 | args: [--fix, --exit-non-zero-on-fix, --config=pyproject.toml] 54 | - id: ruff-format 55 | description: "Formats Python code using Ruff formatter" 56 | types_or: [python, pyi, jupyter] 57 | args: [--config=pyproject.toml] 58 | 59 | - repo: https://github.com/pre-commit/mirrors-mypy 60 | rev: v1.15.0 61 | hooks: 62 | - id: mypy 63 | description: "Performs type checking using mypy" 64 | types_or: [python, pyi, jupyter] 65 | args: [--config-file=pyproject.toml] 66 | ``` 67 | 68 | ## VSCode extensions 69 | 70 | VSCode Extensions は,VSCode の機能を拡張するプラグインで,各種プログラミング言語のサポート,コードのデバッグ,リファクタリング,テキスト編集の強化,外部ツールの統合が可能である.本リポジトリでは,以下の VSCode Extensions を利用している. 71 | 72 | ### python 73 | 74 | - ms-python.python 75 | - ms-python.vscode-pylance 76 | - charliermarsh.ruff 77 | - ms-python.mypy-type-checker 78 | - donjayamanne.python-extension-pack 79 | 80 | ### jupyter 81 | 82 | - ms-toolsai.jupyter 83 | - ms-toolsai.jupyter-keymap 84 | - ms-toolsai.jupyter-renderers 85 | 86 | ### git 87 | 88 | - mhutchie.git-graph 89 | - eamodio.gitlens 90 | - donjayamanne.git-extension-pack 91 | 92 | ### markdown 93 | 94 | - yzhang.markdown-all-in-one 95 | - shd101wyy.markdown-preview-enhanced 96 | 97 | ### shell 98 | 99 | - mads-hartmann.bash-ide-vscode 100 | - timonwong.shellcheck 101 | - foxundermoon.shell-format 102 | 103 | ### visibility 104 | 105 | - mechatroner.rainbow-csv 106 | - GrapeCity.gc-excelviewer 107 | - janisdd.vscode-edit-csv 108 | - monokai.theme-monokai-pro-vscode 109 | - vscode-icons-team.vscode-icons 110 | - MS-CEINTL.vscode-language-pack-ja 111 | 112 | ### others 113 | 114 | - github.copilot 115 | - github.copilot-chat 116 | - aws-toolkit-vscode 117 | - amazonwebservices.amazon-q-vscode 118 | - saoudrizwan.claude-dev 119 | 120 | ## setting.json 121 | 122 | settings.json は,VSCode の設定ファイルで,エディタの挙動や見た目,拡張機能の設定などをカスタマイズできる.本リポジトリでは,以下の設定を利用し,Python コードの保存時に自動で Ruff や mypy を実行している.(`./.devcontainer/devcontainer.json`に記載がある.) 123 | 124 | ```json 125 | { 126 | "terminal.integrated.profiles.linux": { 127 | "bash": { 128 | "path": "/bin/bash" 129 | } 130 | }, 131 | // notebook 132 | "notebook.formatOnSave.enabled": true, 133 | "notebook.codeActionsOnSave": { 134 | "notebook.source.fixAll": "explicit", 135 | "notebook.source.organizeImports": "explicit" 136 | }, 137 | // python 138 | "[python]": { 139 | "editor.formatOnSave": true, 140 | "editor.defaultFormatter": "charliermarsh.ruff", 141 | "editor.codeActionsOnSave": { 142 | "source.fixAll": "explicit", // fix lint violations on-save 143 | "source.organizeImports": "explicit" // organize imports on-save 144 | } 145 | }, 146 | "mypy-type-checker.args": ["--config=${workspaceFolder}/pyproject.toml"], 147 | "python.defaultInterpreterPath": "./.venv/bin/python", 148 | "python.analysis.typeCheckingMode": "basic", 149 | "python.analysis.inlayHints.functionReturnTypes": true, 150 | "python.analysis.inlayHints.variableTypes": true, 151 | "python.analysis.completeFunctionParens": true, 152 | // visibility 153 | "editor.bracketPairColorization.enabled": true, 154 | "editor.guides.bracketPairs": "active", 155 | // markdown 156 | "[markdown]": { 157 | "editor.wordWrap": "bounded", 158 | "editor.defaultFormatter": "esbenp.prettier-vscode" 159 | } 160 | } 161 | ``` 162 | 163 | ## 参考 164 | 165 | - [mlops-starter-sklearn/docs/coding-guidelines.md](https://github.com/Azure/mlops-starter-sklearn/blob/main/docs/coding-guidelines.md) 166 | - [Python Coding Best Practices for Researchers](https://cyberagentailab.github.io/BestPracticesForPythonCoding/) 167 | - [uv だけで Python プロジェクトを管理する](https://zenn.dev/turing_motors/articles/594fbef42a36ee) 168 | - [Python パッケージ管理 [uv] 完全入門](https://speakerdeck.com/mickey_kubo/pythonpatukeziguan-li-uv-wan-quan-ru-men) 169 | - [深層学習を用いた実験における再現可能な環境構築](https://note.com/shunk031/n/n0f0e9e42b5aa) 170 | - [Anthropic で利用されているモダンな Python 開発のベストプラクティス](https://zenn.dev/yareyare/articles/d67aa75b37537c) 171 | -------------------------------------------------------------------------------- /docs/operation_ec2.md: -------------------------------------------------------------------------------- 1 | # EC2 インスタンスの運用 2 | 3 | Cloud9 などで開発する場合,自動シャットダウン機能がデフォルトで提供されているため,インスタンスの消し忘れを防ぐことができる.しかし,VSCode Remote Development を利用して EC2 で開発する場合,自動シャットダウン機能が提供されていないため,消し忘れが発生しやすい.そこで,Lambda と EventBridge を利用し,夜 12 時に全ての EC2 インスタンスを停止させるように運用している.また,特定のインスタンスは停止の対象外にできるようにしている. 4 | 5 | ## 実行コード 6 | 7 | `./ops_ec2/lambda_function.py`を夜 12 時に定期実行している.コードでは,指定のリージョンのインスタンスを全て停止させている. 8 | 9 | ## 工夫点 10 | 11 | 環境変数`EXCLUDED_INSTANCE_IDS`に特定のインスタンスは停止の対象外にできるように工夫している. 12 | 13 | ```python 14 | # ./ops_ec2/lambda_function.py 15 | import boto3 16 | import os 17 | 18 | # env_var-> EXCLUDED_INSTANCE_IDS: 19 | excluded_instance_ids = os.environ['EXCLUDED_INSTANCE_IDS'].split(',') 20 | region = 'ap-northeast-1' 21 | 22 | def lambda_handler(event, context): 23 | ec2 = boto3.client('ec2', region_name=region) 24 | 25 | # Describe EC2 Instances 26 | instances = ec2.describe_instances() 27 | 28 | # Check the EC2 Instances ID and State 29 | for reservation in instances['Reservations']: 30 | for instance in reservation['Instances']: 31 | if instance['InstanceId'] not in excluded_instance_ids and instance['State']['Name'] == 'running': 32 | # Stop EC2 Instances that not equal to instance_id_excluded and in running state 33 | ec2.stop_instances(InstanceIds=[instance['InstanceId']]) 34 | print('Stopping instance: ', instance['InstanceId']) 35 | 36 | return 'Complete stopping instances except ' + ', '.join(excluded_instance_ids) 37 | 38 | ``` 39 | -------------------------------------------------------------------------------- /img/cf-ec2-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ren8k/aws-ec2-devkit-vscode/0197763362d040eb0dfe7ef31cddded3877a9f5b/img/cf-ec2-architecture.png -------------------------------------------------------------------------------- /img/vscode-ssm-ec2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ren8k/aws-ec2-devkit-vscode/0197763362d040eb0dfe7ef31cddded3877a9f5b/img/vscode-ssm-ec2.png -------------------------------------------------------------------------------- /ops_ec2/lambda_function.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import boto3 4 | 5 | # env_var-> EXCLUDED_INSTANCE_IDS: 6 | excluded_instance_ids = os.environ['EXCLUDED_INSTANCE_IDS'].split(',') 7 | region = 'ap-northeast-1' 8 | 9 | def lambda_handler(event, context): 10 | ec2 = boto3.client('ec2', region_name=region) 11 | 12 | # Describe EC2 Instances 13 | instances = ec2.describe_instances() 14 | 15 | # Check the EC2 Instances ID and State 16 | for reservation in instances['Reservations']: 17 | for instance in reservation['Instances']: 18 | if instance['InstanceId'] not in excluded_instance_ids and instance['State']['Name'] == 'running': 19 | # Stop EC2 Instances that not equal to instance_id_excluded and in running state 20 | ec2.stop_instances(InstanceIds=[instance['InstanceId']]) 21 | print('Stopping instance: ', instance['InstanceId']) 22 | 23 | return 'Complete stopping instances except ' + ', '.join(excluded_instance_ids) 24 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "app" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.13" 7 | dependencies = [] 8 | 9 | [build-system] 10 | requires = ["hatchling"] 11 | build-backend = "hatchling.build" 12 | 13 | [tool.hatch.build.targets.wheel] 14 | packages = ["src"] 15 | 16 | [project.scripts] 17 | main = "src.main:main" 18 | 19 | # https://zenn.dev/turing_motors/articles/0f1a764d14f581 20 | [tool.ruff] 21 | exclude = [".git", ".mypy_cache", ".ruff_cache", ".venv", "third_party"] 22 | line-length = 160 23 | target-version = "py313" 24 | 25 | [tool.ruff.lint] 26 | fixable = ["ALL"] 27 | unfixable = [] 28 | select = [ 29 | "A", # flake8-builtin 30 | "B", # flake8-bugbear 31 | "E", # pycodestyle error 32 | "F", # Pyflakes 33 | "I", # isort 34 | "N", # pep8-naming 35 | "W", # pycodestyle warning 36 | "PL", # Pylint 37 | "UP", # pyupgrade 38 | ] 39 | ignore = [ 40 | "B905", # Zip-without-explicit-strict 41 | "E501", # Line too long 42 | "F403", # Unable to detect undefined names 43 | "N812", # Lowercase imported as non-lowercase 44 | "N999", # Invalid module name 45 | "PLR0912", # Too many branches 46 | "PLR0913", # Too many arguments in function definition 47 | "PLR2004", # Magic value used in comparison 48 | ] 49 | 50 | [tool.ruff.format] 51 | quote-style = "double" 52 | line-ending = "auto" 53 | 54 | [tool.mypy] 55 | allow_redefinition = true 56 | allow_untyped_globals = false 57 | check_untyped_defs = true 58 | color_output = true 59 | disallow_incomplete_defs = true 60 | disallow_subclassing_any = false 61 | disallow_untyped_calls = false 62 | disallow_untyped_decorators = false 63 | disallow_untyped_defs = true 64 | error_summary = true 65 | ignore_missing_imports = true 66 | implicit_reexport = true 67 | namespace_packages = true 68 | no_implicit_optional = true 69 | pretty = true 70 | show_column_numbers = true 71 | show_error_codes = true 72 | show_error_context = true 73 | show_traceback = true 74 | strict = true 75 | warn_no_return = true 76 | warn_redundant_casts = true 77 | warn_return_any = true 78 | warn_unreachable = true 79 | warn_unused_configs = true 80 | warn_unused_ignores = false 81 | -------------------------------------------------------------------------------- /setup/cf-template/cf-ec2.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: AWS EC2 environment for remote connection from VSCode to experiment with deep learning. This file create EC2, IAMRole, Security Group, and EC2 Key pair. 3 | Parameters: 4 | ImageId: 5 | Description: Amazon Machine Image (AMI) 6 | Type: String 7 | Default: ami-09c1f9fce82b9f2af 8 | EC2InstanceType: 9 | Description: EC2 instance type on which IDE runs 10 | Type: String 11 | Default: g4dn.xlarge 12 | VolumeSize: 13 | Description: root volume size 14 | Type: String 15 | Default: 100 16 | VPCId: 17 | Description: VPC ID where the instance will be launched (For example, check your default vpc.) 18 | Type: String 19 | Default: vpc-XXXXXXXXXXXXXXXXX 20 | SubnetId: 21 | Description: Public subnet in vpc (For example, check your pucblic-subnet ip in default vpc.) 22 | Type: String 23 | Default: subnet-XXXXXXXXXXXXXXXXX 24 | Resources: 25 | EC2InstanceRole: 26 | Type: AWS::IAM::Role 27 | Properties: 28 | AssumeRolePolicyDocument: 29 | Version: "2012-10-17" 30 | Statement: 31 | - Effect: Allow 32 | Principal: 33 | Service: 34 | - ec2.amazonaws.com 35 | - sagemaker.amazonaws.com 36 | Action: 37 | - sts:AssumeRole 38 | ManagedPolicyArns: 39 | - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore 40 | - arn:aws:iam::aws:policy/AmazonS3FullAccess 41 | - arn:aws:iam::aws:policy/AWSCodeCommitFullAccess 42 | - arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilderECRContainerBuilds 43 | - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess 44 | - arn:aws:iam::aws:policy/SecretsManagerReadWrite 45 | - arn:aws:iam::aws:policy/AWSLambda_FullAccess 46 | - arn:aws:iam::aws:policy/AmazonBedrockFullAccess 47 | - arn:aws:iam::aws:policy/AmazonECS_FullAccess 48 | RoleName: !Sub ${AWS::StackName}-cf-remote-development-role 49 | Tags: 50 | - Key: Name 51 | Value: !Sub ${AWS::StackName}-cf-remote-development-role 52 | EC2InstanceProfile: 53 | Type: AWS::IAM::InstanceProfile 54 | Properties: 55 | Roles: 56 | - !Ref EC2InstanceRole 57 | NewKeyPair: 58 | Type: AWS::EC2::KeyPair 59 | Properties: 60 | KeyName: !Sub ${AWS::StackName}-cf-key 61 | Tags: 62 | - Key: Name 63 | Value: !Sub ${AWS::StackName}-cf-key 64 | EC2SecurityGroup: 65 | Type: AWS::EC2::SecurityGroup 66 | Properties: 67 | VpcId: !Ref VPCId 68 | GroupDescription: for remote development 69 | GroupName: !Sub ${AWS::StackName}-cf-sg 70 | SecurityGroupEgress: 71 | - CidrIp: 0.0.0.0/0 72 | FromPort: -1 73 | IpProtocol: -1 74 | ToPort: -1 75 | Tags: 76 | - Key: Name 77 | Value: !Sub ${AWS::StackName}-cf-sg 78 | EC2Instance: 79 | Type: AWS::EC2::Instance 80 | Properties: 81 | ImageId: !Ref ImageId 82 | InstanceType: !Ref EC2InstanceType 83 | KeyName: !Ref NewKeyPair 84 | NetworkInterfaces: 85 | - AssociatePublicIpAddress: true 86 | DeviceIndex: 0 87 | SubnetId: !Ref SubnetId 88 | GroupSet: 89 | - !GetAtt EC2SecurityGroup.GroupId 90 | IamInstanceProfile: !Ref EC2InstanceProfile 91 | BlockDeviceMappings: 92 | - DeviceName: /dev/sda1 93 | Ebs: 94 | VolumeType: gp3 95 | VolumeSize: !Ref VolumeSize 96 | DeleteOnTermination: "true" 97 | Encrypted: "false" 98 | UserData: !Base64 | 99 | #!/bin/bash 100 | export HOME=/home/ubuntu 101 | 102 | echo upgrade git 103 | sudo -E add-apt-repository ppa:git-core/ppa -y 104 | sudo apt-get update && sudo apt-get -y upgrade 105 | git config --global init.defaultBranch main 106 | 107 | echo setup git credential 108 | git config --global credential.helper '!aws codecommit credential-helper $@' 109 | git config --global credential.UseHttpPath true 110 | 111 | echo install uv 112 | curl -LsSf https://astral.sh/uv/install.sh | sh 113 | 114 | echo add pytorch venv activation to user profile 115 | echo "source /opt/pytorch/bin/activate" >> /home/ubuntu/.bashrc 116 | Tags: 117 | - Key: Name 118 | Value: !Sub ${AWS::StackName}-cf-ec2 119 | Outputs: 120 | InstanceId: 121 | Description: The Instance ID 122 | Value: !Ref EC2Instance 123 | InstanceRoleArn: 124 | Description: The Instance Role ARN 125 | Value: !GetAtt EC2InstanceRole.Arn 126 | KeyID: 127 | Description: The Key ID 128 | Value: !GetAtt NewKeyPair.KeyPairId 129 | -------------------------------------------------------------------------------- /setup/check_vm_env/check_cuda_torch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # check cuda 4 | echo "==============check cuda==============" 5 | nvcc -V 6 | 7 | # check gpu 8 | echo "==============check gpu==============" 9 | nvidia-smi 10 | 11 | # check torch 12 | echo "==============check torch==============" 13 | echo "if you exec at first time, you might wait for a while..." 14 | python -c "import torch; print(f'torch.__version__: {torch.__version__}')" 15 | python -c "import torch; print(f'torch.cuda.is_available(): {torch.cuda.is_available()}')" 16 | -------------------------------------------------------------------------------- /setup/check_vm_env/mnist_example/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /setup/check_vm_env/mnist_example/mnist.py: -------------------------------------------------------------------------------- 1 | # This code is cloned from https://github.com/pytorch/examples/blob/main/mnist/main.py 2 | 3 | from __future__ import print_function 4 | import argparse 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | import torch.optim as optim 9 | from torchvision import datasets, transforms 10 | from torch.optim.lr_scheduler import StepLR 11 | 12 | 13 | class Net(nn.Module): 14 | def __init__(self): 15 | super(Net, self).__init__() 16 | self.conv1 = nn.Conv2d(1, 32, 3, 1) 17 | self.conv2 = nn.Conv2d(32, 64, 3, 1) 18 | self.dropout1 = nn.Dropout(0.25) 19 | self.dropout2 = nn.Dropout(0.5) 20 | self.fc1 = nn.Linear(9216, 128) 21 | self.fc2 = nn.Linear(128, 10) 22 | 23 | def forward(self, x): 24 | x = self.conv1(x) 25 | x = F.relu(x) 26 | x = self.conv2(x) 27 | x = F.relu(x) 28 | x = F.max_pool2d(x, 2) 29 | x = self.dropout1(x) 30 | x = torch.flatten(x, 1) 31 | x = self.fc1(x) 32 | x = F.relu(x) 33 | x = self.dropout2(x) 34 | x = self.fc2(x) 35 | output = F.log_softmax(x, dim=1) 36 | return output 37 | 38 | 39 | def train(args, model, device, train_loader, optimizer, epoch): 40 | model.train() 41 | for batch_idx, (data, target) in enumerate(train_loader): 42 | data, target = data.to(device), target.to(device) 43 | optimizer.zero_grad() 44 | output = model(data) 45 | loss = F.nll_loss(output, target) 46 | loss.backward() 47 | optimizer.step() 48 | if batch_idx % args.log_interval == 0: 49 | print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( 50 | epoch, batch_idx * len(data), len(train_loader.dataset), 51 | 100. * batch_idx / len(train_loader), loss.item())) 52 | if args.dry_run: 53 | break 54 | 55 | 56 | def test(model, device, test_loader): 57 | model.eval() 58 | test_loss = 0 59 | correct = 0 60 | with torch.no_grad(): 61 | for data, target in test_loader: 62 | data, target = data.to(device), target.to(device) 63 | output = model(data) 64 | test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss 65 | pred = output.argmax(dim=1, keepdim=True) # get the index of the max log-probability 66 | correct += pred.eq(target.view_as(pred)).sum().item() 67 | 68 | test_loss /= len(test_loader.dataset) 69 | 70 | print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( 71 | test_loss, correct, len(test_loader.dataset), 72 | 100. * correct / len(test_loader.dataset))) 73 | 74 | 75 | def main(): 76 | # Training settings 77 | parser = argparse.ArgumentParser(description='PyTorch MNIST Example') 78 | parser.add_argument('--batch-size', type=int, default=64, metavar='N', 79 | help='input batch size for training (default: 64)') 80 | parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N', 81 | help='input batch size for testing (default: 1000)') 82 | parser.add_argument('--epochs', type=int, default=14, metavar='N', 83 | help='number of epochs to train (default: 14)') 84 | parser.add_argument('--lr', type=float, default=1.0, metavar='LR', 85 | help='learning rate (default: 1.0)') 86 | parser.add_argument('--gamma', type=float, default=0.7, metavar='M', 87 | help='Learning rate step gamma (default: 0.7)') 88 | parser.add_argument('--no-cuda', action='store_true', default=False, 89 | help='disables CUDA training') 90 | parser.add_argument('--no-mps', action='store_true', default=False, 91 | help='disables macOS GPU training') 92 | parser.add_argument('--dry-run', action='store_true', default=False, 93 | help='quickly check a single pass') 94 | parser.add_argument('--seed', type=int, default=1, metavar='S', 95 | help='random seed (default: 1)') 96 | parser.add_argument('--log-interval', type=int, default=10, metavar='N', 97 | help='how many batches to wait before logging training status') 98 | parser.add_argument('--save-model', action='store_true', default=False, 99 | help='For Saving the current Model') 100 | args = parser.parse_args() 101 | use_cuda = not args.no_cuda and torch.cuda.is_available() 102 | use_mps = not args.no_mps and torch.backends.mps.is_available() 103 | 104 | torch.manual_seed(args.seed) 105 | 106 | if use_cuda: 107 | device = torch.device("cuda") 108 | elif use_mps: 109 | device = torch.device("mps") 110 | else: 111 | device = torch.device("cpu") 112 | 113 | train_kwargs = {'batch_size': args.batch_size} 114 | test_kwargs = {'batch_size': args.test_batch_size} 115 | if use_cuda: 116 | cuda_kwargs = {'num_workers': 1, 117 | 'pin_memory': True, 118 | 'shuffle': True} 119 | train_kwargs.update(cuda_kwargs) 120 | test_kwargs.update(cuda_kwargs) 121 | 122 | transform=transforms.Compose([ 123 | transforms.ToTensor(), 124 | transforms.Normalize((0.1307,), (0.3081,)) 125 | ]) 126 | dataset1 = datasets.MNIST('../data', train=True, download=True, 127 | transform=transform) 128 | dataset2 = datasets.MNIST('../data', train=False, 129 | transform=transform) 130 | train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs) 131 | test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs) 132 | 133 | model = Net().to(device) 134 | optimizer = optim.Adadelta(model.parameters(), lr=args.lr) 135 | 136 | scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma) 137 | for epoch in range(1, args.epochs + 1): 138 | train(args, model, device, train_loader, optimizer, epoch) 139 | test(model, device, test_loader) 140 | scheduler.step() 141 | 142 | if args.save_model: 143 | torch.save(model.state_dict(), "mnist_cnn.pt") 144 | 145 | 146 | if __name__ == '__main__': 147 | main() 148 | -------------------------------------------------------------------------------- /setup/coding_agent/claude-code/README.md: -------------------------------------------------------------------------------- 1 | # Claude Code セットアップ (on EC2) 2 | 3 | - `bash setup_claude_code.sh` を実行する 4 | - `source ~/.profile` を実行する 5 | - `claude` コマンドを実行する 6 | - terminal setup では,`2` を選択する (下図参照) 7 | - `1` を選択すると,[以下のエラー](https://github.com/anthropics/claude-code/issues/193)が出る. 8 | - `Error: Failed to install VSCode terminal Shift+Enter key binding` 9 | 10 | ``` 11 | ╭──────────────────────────╮ 12 | │ ✻ Welcome to Claude Code │ 13 | ╰──────────────────────────╯ 14 | 15 | Use Claude Code's terminal setup? 16 | 17 | For the optimal coding experience, enable the recommended settings 18 | for your terminal: Shift+Enter for newlines 19 | 20 | 1. Yes, use recommended settings 21 | ❯ 2. No, maybe later with /terminal-setup 22 | 23 | Enter to confirm · Esc to skip 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /setup/coding_agent/claude-code/setup_claude_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ============================================================================== 4 | # Claude Code setup script for EC2 5 | # This script installs Node.js, Claude Code and adds configuration to ~/.profile 6 | # ============================================================================== 7 | 8 | set -e # Exit on error 9 | 10 | # ------------------------------------------------------------------------------ 11 | # Step 1: Install Node.js via nvm 12 | # ------------------------------------------------------------------------------ 13 | echo "Installing Node.js via nvm..." 14 | 15 | # Download and install nvm 16 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash 17 | 18 | # Load nvm without restarting the shell 19 | \. "$HOME/.nvm/nvm.sh" 20 | 21 | # Install Node.js 22 | nvm install 22 23 | 24 | # Verify installation 25 | echo "Verifying Node.js installation..." 26 | node -v # Should display "v22.x.x" 27 | nvm current # Should display "v22.x.x" 28 | npm -v # Should display npm version 29 | 30 | # ------------------------------------------------------------------------------ 31 | # Step 2: Install Claude Code 32 | # ------------------------------------------------------------------------------ 33 | echo 34 | echo "Installing Claude Code..." 35 | 36 | npm install -g @anthropic-ai/claude-code 37 | 38 | if [ $? -eq 0 ]; then 39 | echo "Claude Code installed successfully" 40 | else 41 | echo "Failed to install Claude Code" 42 | exit 1 43 | fi 44 | 45 | # ------------------------------------------------------------------------------ 46 | # Step 3: Configure Claude Code for AWS Bedrock 47 | # ------------------------------------------------------------------------------ 48 | echo 49 | echo "Setting up Claude Code configuration..." 50 | 51 | # Check if the configuration already exists 52 | if grep -q "# Claude Code settings" ~/.profile 2>/dev/null; then 53 | echo "Claude Code settings already exist in ~/.profile" 54 | echo "Skipping configuration..." 55 | else 56 | # Append Claude Code settings to ~/.profile 57 | cat >> ~/.profile << 'EOF' 58 | 59 | # Claude Code settings 60 | export CLAUDE_CODE_USE_BEDROCK=1 61 | export ANTHROPIC_MODEL="us.anthropic.claude-opus-4-20250514-v1:0" 62 | # export ANTHROPIC_MODEL="us.anthropic.claude-sonnet-4-20250514-v1:0" 63 | export AWS_REGION="us-west-2" 64 | # export AWS_PROFILE="your-profile" # Uncomment if using specific AWS profile 65 | EOF 66 | 67 | echo "Claude Code settings added to ~/.profile" 68 | fi 69 | 70 | # ------------------------------------------------------------------------------ 71 | # Step 4: Apply configuration 72 | # ------------------------------------------------------------------------------ 73 | echo 74 | echo "Applying configuration..." 75 | source ~/.profile 76 | 77 | echo 78 | echo "Claude Code setup completed!" 79 | echo "Run 'claude' to start using Claude Code" 80 | -------------------------------------------------------------------------------- /setup/coding_agent/cline/.clineignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .coverage 3 | .mypy_cache 4 | .pytest_cache 5 | .ruff_cache 6 | .ipynb_checkpoints 7 | .venv 8 | *.egg-info 9 | .env 10 | 11 | # user setting 12 | -------------------------------------------------------------------------------- /setup/coding_agent/cline/.clinerules: -------------------------------------------------------------------------------- 1 | # 基本設定 2 | - 出力言語:日本語 3 | - コードスタイル:PEP 8準拠 4 | - ドキュメント形式:Markdown 5 | 6 | # プロジェクト構造 7 | - AWS EC2上でVSCode Dev Containersを利用した開発環境のプロジェクト構造: 8 | ``` 9 | - .devcontainer/ # Docker環境設定 10 | - docs/ # ドキュメント(コーディングガイドライン、運用手順など) 11 | - src/ # メインのソースコード 12 | - pyproject.toml # プロジェクト設定とパッケージ管理 13 | - uv.lock # パッケージのロックファイル 14 | ``` 15 | 16 | # 技術スタック 17 | - 言語:Python 3.13 18 | - パッケージマネージャ:uv 19 | - Linter/Formatter:Ruff 20 | - 型チェッカー:mypy 21 | - フレームワーク: 22 | - 深層学習:PyTorch 23 | - AWS連携:boto3, sagemaker 24 | - CI/CD:pre-commit 25 | - コンテナ:Docker(Dev Containers経由) 26 | 27 | # 開発環境 28 | - AWS EC2(Ubuntu 22.04) 29 | - VSCode Remote SSH + Dev Containers 30 | - GPU環境:NVIDIA Driver 570.86.15, CUDA 12.6, cuDNN 31 | 32 | # 行動指針 33 | ## タスクの進め方 34 | 1. ユーザの依頼に対して、そのタスクをどのように実現できるか計画を立て、その計画をまずドキュメントにまとめます 35 | - ドキュメントは`outputs/cline`にユーザの依頼とそれに対する計画がわかるようにmarkdown形式でまとめます 36 | - 再度計画を立てると数$消費されるのを防ぐため、必ず計画はドキュメントにまとめてください 37 | - タスクの分割粒度ですが、各タスクごとにテストコードを記載できる程度の粒度でまとめてください 38 | - 注意:ユーザの指示の範囲内のみでタスクを考え、指示を超えた実装内容は絶対に含めないでください 39 | 2. ドキュメントが完成したら、計画の通りにタスクを実装します 40 | - タスクのスコープから外れる実装は絶対に行わないでください 41 | - タスクの実装が完了したら、必ずテストコードを記載してください 42 | 43 | ## コード実装 44 | - 既存のディレクトリ構造を遵守 45 | - uvを使用してパッケージ管理:`uv add/remove ` 46 | - 仮想環境の使用:`uv run python`または`.venv/bin/activate` 47 | 48 | ## 静的解析 49 | - Ruffによるlint/format:プロジェクトルートの`pyproject.toml`設定に従う 50 | - mypyによる型チェック:プロジェクトルートの`pyproject.toml`設定に従う 51 | 52 | ## セキュリティ 53 | - 秘密情報(APIキー、パスワードなど)はコードに直接記述しない 54 | - AWS Systems Manager Parameter StoreまたはSecrets Managerを使用 55 | - SSH接続はSSM Session Manager経由で実施 56 | 57 | ## ドキュメント作成 58 | - README.mdは既存のフォーマットに従う 59 | - 技術的な詳細は`docs/`ディレクトリに配置 60 | - コメントは日本語で記述可能 61 | 62 | ## エラーハンドリング 63 | - AWS API呼び出し時は適切な例外処理を実装 64 | - ネットワークエラーやタイムアウトを考慮 65 | - エラーメッセージは日本語で分かりやすく記述 66 | -------------------------------------------------------------------------------- /setup/coding_agent/cline/README.md: -------------------------------------------------------------------------------- 1 | # Cline セットアップ (on EC2) 2 | 3 | 以下のファイルをルートディレクトリに配置する. 4 | 5 | - `.clineignore` 6 | - `.clinerules` 7 | 8 | `.clinerules`については,各々が利用しやすいようにカスタマイズすること.(別に無くても良い.) 9 | -------------------------------------------------------------------------------- /setup/make_new_project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # ======================================== 6 | # Configuration 7 | # ======================================== 8 | 9 | # Colors for output 10 | readonly RED='\033[0;31m' 11 | readonly GREEN='\033[0;32m' 12 | readonly YELLOW='\033[1;33m' 13 | readonly BLUE='\033[0;34m' 14 | readonly NC='\033[0m' # No Color 15 | 16 | # Docker environment options 17 | declare -A DOCKER_ENVS=( 18 | ["1"]="cpu-uv:CPU環境、uvパッケージマネージャ" 19 | ["2"]="gpu-uv:GPU環境、uvパッケージマネージャ" 20 | ["3"]="gpu-sagemaker:GPU環境、SageMaker用" 21 | ) 22 | 23 | # Files to copy 24 | readonly CONFIG_FILES=( 25 | ".gitignore" 26 | ".pre-commit-config.yaml" 27 | "pyproject.toml" 28 | "uv.lock" 29 | ) 30 | 31 | # Project name validation pattern 32 | readonly PROJECT_NAME_PATTERN='^[a-zA-Z0-9_-]+$' 33 | 34 | # ======================================== 35 | # Utility Functions 36 | # ======================================== 37 | 38 | print_info() { 39 | echo -e "${BLUE}[INFO]${NC} $1" 40 | } 41 | 42 | print_success() { 43 | echo -e "${GREEN}[SUCCESS]${NC} $1" 44 | } 45 | 46 | print_warning() { 47 | echo -e "${YELLOW}[WARNING]${NC} $1" 48 | } 49 | 50 | print_error() { 51 | echo -e "${RED}[ERROR]${NC} $1" 52 | } 53 | 54 | # ======================================== 55 | # Setup Functions 56 | # ======================================== 57 | 58 | setup_directories() { 59 | local script_path="${BASH_SOURCE[0]}" 60 | SCRIPT_DIR="$(cd "$(dirname "$script_path")" && pwd)" 61 | TEMPLATE_ROOT="$(dirname "$SCRIPT_DIR")" 62 | PARENT_DIR="$(dirname "$TEMPLATE_ROOT")" 63 | } 64 | 65 | # ======================================== 66 | # Validation Functions 67 | # ======================================== 68 | 69 | validate_project_name() { 70 | local name="$1" 71 | 72 | if [[ -z "$name" ]]; then 73 | print_error "プロジェクト名は必須です。" 74 | return 1 75 | fi 76 | 77 | if [[ ! "$name" =~ $PROJECT_NAME_PATTERN ]]; then 78 | print_error "プロジェクト名は英数字、ハイフン、アンダースコアのみ使用できます。" 79 | return 1 80 | fi 81 | 82 | local project_dir="$PARENT_DIR/$name" 83 | if [[ -d "$project_dir" ]]; then 84 | print_error "ディレクトリ '$name' は既に存在します。" 85 | return 1 86 | fi 87 | 88 | return 0 89 | } 90 | 91 | validate_docker_env_choice() { 92 | local choice="$1" 93 | 94 | if [[ -n "${DOCKER_ENVS[$choice]:-}" ]]; then 95 | return 0 96 | else 97 | print_error "1, 2, または 3 を選択してください。" 98 | return 1 99 | fi 100 | } 101 | 102 | # ======================================== 103 | # Input Functions 104 | # ======================================== 105 | 106 | prompt_project_name() { 107 | local project_name 108 | 109 | while true; do 110 | echo 111 | read -r -p "プロジェクト名を入力してください: " project_name 112 | 113 | if validate_project_name "$project_name"; then 114 | PROJECT_NAME="$project_name" 115 | PROJECT_DIR="$PARENT_DIR/$project_name" 116 | break 117 | fi 118 | done 119 | } 120 | 121 | prompt_docker_environment() { 122 | echo 123 | print_info "使用するDocker環境を選択してください:" 124 | 125 | local i 126 | for i in "${!DOCKER_ENVS[@]}"; do 127 | local env_info="${DOCKER_ENVS[$i]}" 128 | local env_name="${env_info%%:*}" 129 | local env_desc="${env_info#*:}" 130 | echo "$i) $env_name ($env_desc)" 131 | done | sort -n 132 | 133 | local choice 134 | while true; do 135 | read -r -p "選択 (1-3): " choice 136 | 137 | if validate_docker_env_choice "$choice"; then 138 | DOCKER_ENV="${DOCKER_ENVS[$choice]%%:*}" 139 | break 140 | fi 141 | done 142 | } 143 | 144 | confirm_settings() { 145 | print_info "選択された設定:" 146 | echo " プロジェクト名: $PROJECT_NAME" 147 | echo " Docker環境: $DOCKER_ENV" 148 | echo 149 | 150 | local reply 151 | read -r -p "この設定で続行しますか? (y/N): " reply 152 | 153 | if [[ ! $reply =~ ^[Yy]$ ]]; then 154 | print_info "キャンセルしました。" 155 | return 1 156 | fi 157 | 158 | return 0 159 | } 160 | 161 | # ======================================== 162 | # Project Creation Functions 163 | # ======================================== 164 | 165 | create_project_directory() { 166 | print_info "プロジェクトディレクトリを作成中..." 167 | 168 | if ! mkdir -p "$PROJECT_DIR"; then 169 | print_error "プロジェクトディレクトリの作成に失敗しました。" 170 | return 1 171 | fi 172 | 173 | return 0 174 | } 175 | 176 | copy_template_files() { 177 | print_info "必要なファイルをコピー中..." 178 | 179 | local error_occurred=false 180 | 181 | # Copy .devcontainer directory 182 | if ! cp -r "$TEMPLATE_ROOT/.devcontainer/$DOCKER_ENV" "$PROJECT_DIR/.devcontainer"; then 183 | print_error ".devcontainerディレクトリのコピーに失敗しました。" 184 | error_occurred=true 185 | fi 186 | 187 | # Copy src directory 188 | if ! cp -r "$TEMPLATE_ROOT/src" "$PROJECT_DIR/"; then 189 | print_error "srcディレクトリのコピーに失敗しました。" 190 | error_occurred=true 191 | fi 192 | 193 | # Copy configuration files 194 | local file 195 | for file in "${CONFIG_FILES[@]}"; do 196 | if ! cp "$TEMPLATE_ROOT/$file" "$PROJECT_DIR/"; then 197 | print_error "$file のコピーに失敗しました。" 198 | error_occurred=true 199 | fi 200 | done 201 | 202 | # Create README.md 203 | if ! echo "# $PROJECT_NAME" > "$PROJECT_DIR/README.md"; then 204 | print_error "README.mdの作成に失敗しました。" 205 | error_occurred=true 206 | fi 207 | 208 | if [[ "$error_occurred" == "true" ]]; then 209 | return 1 210 | fi 211 | 212 | return 0 213 | } 214 | 215 | update_project_files() { 216 | print_info "ファイルの内容を更新中..." 217 | 218 | local error_occurred=false 219 | 220 | # Update devcontainer.json name 221 | if ! sed -i "s/\"name\": \"$DOCKER_ENV\"/\"name\": \"$PROJECT_NAME\"/" \ 222 | "$PROJECT_DIR/.devcontainer/devcontainer.json"; then 223 | print_error "devcontainer.jsonの更新に失敗しました。" 224 | error_occurred=true 225 | fi 226 | 227 | # Update pyproject.toml name 228 | if ! sed -i "s/name = \"app\"/name = \"$PROJECT_NAME\"/" \ 229 | "$PROJECT_DIR/pyproject.toml"; then 230 | print_error "pyproject.tomlの更新に失敗しました。" 231 | error_occurred=true 232 | fi 233 | 234 | # Update uv.lock name 235 | if ! sed -i "s/name = \"app\"/name = \"$PROJECT_NAME\"/" \ 236 | "$PROJECT_DIR/uv.lock"; then 237 | print_error "uv.lockの更新に失敗しました。" 238 | error_occurred=true 239 | fi 240 | 241 | # Fix initializeCommand path for gpu-sagemaker environment 242 | if [[ "$DOCKER_ENV" == "gpu-sagemaker" ]]; then 243 | if ! sed -i "s|\"initializeCommand\": \"bash \${localWorkspaceFolder}/.devcontainer/gpu-sagemaker/init.sh\"|\"initializeCommand\": \"bash \${localWorkspaceFolder}/.devcontainer/init.sh\"|" \ 244 | "$PROJECT_DIR/.devcontainer/devcontainer.json"; then 245 | print_error "gpu-sagemaker用のinitializeCommandパスの更新に失敗しました。" 246 | error_occurred=true 247 | fi 248 | fi 249 | 250 | if [[ "$error_occurred" == "true" ]]; then 251 | return 1 252 | fi 253 | 254 | return 0 255 | } 256 | 257 | initialize_git_repository() { 258 | print_info "Gitリポジトリを初期化中..." 259 | 260 | if ! (cd "$PROJECT_DIR" && git init); then 261 | print_error "Gitリポジトリの初期化に失敗しました。" 262 | return 1 263 | fi 264 | 265 | return 0 266 | } 267 | 268 | cleanup_on_error() { 269 | if [[ -d "$PROJECT_DIR" ]]; then 270 | print_warning "エラーが発生したため、作成されたディレクトリを削除します..." 271 | rm -rf "$PROJECT_DIR" 272 | fi 273 | } 274 | 275 | show_completion_message() { 276 | print_success "プロジェクト '$PROJECT_NAME' が正常に作成されました!" 277 | print_info "プロジェクトディレクトリ: $PROJECT_DIR" 278 | echo 279 | print_info "次のステップ:" 280 | echo "1. cd $PROJECT_DIR" 281 | echo "2. VS Code でディレクトリを開く" 282 | echo "3. Dev Container でコンテナを起動する" 283 | echo "4. 開発を開始!" 284 | } 285 | 286 | # ======================================== 287 | # Main Function 288 | # ======================================== 289 | 290 | main() { 291 | # Setup environment 292 | setup_directories 293 | 294 | # Show header 295 | print_info "AWS EC2 DevKit Project Template Generator" 296 | echo "==========================================" 297 | 298 | # Get user inputs 299 | prompt_project_name 300 | prompt_docker_environment 301 | 302 | # Confirm settings 303 | if ! confirm_settings; then 304 | exit 0 305 | fi 306 | 307 | # Create project with error handling 308 | { 309 | create_project_directory && 310 | copy_template_files && 311 | update_project_files && 312 | initialize_git_repository 313 | } || { 314 | print_error "プロジェクトの作成中にエラーが発生しました。" 315 | cleanup_on_error 316 | exit 1 317 | } 318 | 319 | # Show completion message 320 | show_completion_message 321 | } 322 | 323 | # ======================================== 324 | # Script Entry Point 325 | # ======================================== 326 | 327 | # Run main function if script is executed directly 328 | if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then 329 | main "$@" 330 | fi 331 | -------------------------------------------------------------------------------- /setup/ssh/ssh_setup_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set variables(cf output) 4 | KEY_ID="key-XXXXXXXXXXXXXXXXX" 5 | INSTANCE_ID="i-XXXXXXXXXXXXXXXXX" 6 | SECRET_KEY="ec2_secret_key.pem" 7 | KEY_PREFIX="/ec2/keypair" 8 | SSH_CONFIG="config" 9 | SSH_CONFIG_DIR="${HOME}/.ssh" 10 | SSH_CONFIG_PATH="${SSH_CONFIG_DIR}/${SSH_CONFIG}" 11 | SECRET_KEY_PATH="${SSH_CONFIG_DIR}/${SECRET_KEY}" 12 | HOST="ec2" 13 | USER="ubuntu" 14 | 15 | echo "Checking and creating .ssh directory if necessary..." 16 | if [ ! -d $SSH_CONFIG_DIR ]; then 17 | echo "Creating .ssh directory..." 18 | mkdir -p $SSH_CONFIG_DIR 19 | chmod 700 $SSH_CONFIG_DIR 20 | fi 21 | 22 | echo "Retrieving and saving the secret key..." 23 | aws ssm get-parameter --name $KEY_PREFIX/$KEY_ID --with-decryption --query "Parameter.Value" --output text >$SECRET_KEY_PATH 24 | 25 | echo "Setting permissions for the secret key..." 26 | chmod 600 $SECRET_KEY_PATH 27 | 28 | echo "Updating SSH configuration..." 29 | cat <>$SSH_CONFIG_PATH 30 | host $HOST 31 | HostName $INSTANCE_ID 32 | Port 22 33 | User $USER 34 | IdentityFile $SECRET_KEY_PATH 35 | TCPKeepAlive yes 36 | IdentitiesOnly yes 37 | ServerAliveInterval 60 38 | ForwardAgent yes 39 | ForwardX11 yes 40 | ProxyCommand bash -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'" 41 | EOF 42 | 43 | echo "Configuration complete." 44 | -------------------------------------------------------------------------------- /setup/ssh/ssh_setup_win.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | REM Set variables(cf output) 5 | set "KEY_ID=key-XXXXXXXXXXXXXXXXX" 6 | set "INSTANCE_ID=i-XXXXXXXXXXXXXXXXX" 7 | set "SECRET_KEY=ec2_secret_key.pem" 8 | set "KEY_PREFIX=/ec2/keypair" 9 | set "SSH_CONFIG=config" 10 | set "SSH_CONFIG_DIR=%USERPROFILE%\.ssh" 11 | set "SSH_CONFIG_PATH=%SSH_CONFIG_DIR%\%SSH_CONFIG%" 12 | set "SECRET_KEY_PATH=%SSH_CONFIG_DIR%\%SECRET_KEY%" 13 | set "HOST=ec2" 14 | set "USER=ubuntu" 15 | 16 | REM If not exist "%SSH_CONFIG_DIR%" mkdir "%SSH_CONFIG_DIR%" 17 | if not exist "%SSH_CONFIG_DIR%" ( 18 | echo Creating .ssh directory... 19 | mkdir "%SSH_CONFIG_DIR%" 20 | ) 21 | 22 | REM Get key pair from parameter store and save to file 23 | echo Retrieving and saving the secret key... 24 | aws ssm get-parameter --name "%KEY_PREFIX%/%KEY_ID%" --with-decryption --query "Parameter.Value" --output text > "%SECRET_KEY_PATH%" 25 | 26 | REM Change permission 27 | echo Setting file permissions... 28 | icacls "%SECRET_KEY_PATH%" /inheritance:r 29 | icacls "%SECRET_KEY_PATH%" /grant "%USERNAME%:F" 30 | 31 | REM Postscript ssh config 32 | echo Updating SSH configuration... 33 | ( 34 | echo host %HOST% 35 | echo HostName %INSTANCE_ID% 36 | echo Port 22 37 | echo User %USER% 38 | echo IdentityFile %SECRET_KEY_PATH% 39 | echo TCPKeepAlive yes 40 | echo IdentitiesOnly yes 41 | echo ServerAliveInterval 60 42 | echo ForwardAgent yes 43 | echo ForwardX11 yes 44 | echo ProxyCommand C:\Program Files\Amazon\AWSCLIV2\aws.exe ssm start-session --target %%h --document-name AWS-StartSSHSession --parameters "portNumber=%%p" 45 | ) >> "%SSH_CONFIG_PATH%" 46 | 47 | echo Configuration complete. 48 | endlocal 49 | -------------------------------------------------------------------------------- /setup/vscode/vscode_local_setup_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # install vscode extension 4 | code --install-extension ms-vscode-remote.vscode-remote-extensionpack 5 | code --install-extension amazonwebservices.aws-toolkit-vscode 6 | code --install-extension alefragnani.project-manager 7 | code --install-extension jabrythehutt.awsrd 8 | echo finish 9 | -------------------------------------------------------------------------------- /setup/vscode/vscode_local_setup_win.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | cd %~dp0 4 | 5 | @REM set git credential helper (if you need to clone repos from aws codecommit) 6 | @REM git config --global credential.helper "!aws codecommit credential-helper $@" 7 | @REM git config --global credential.UseHttpPath true 8 | 9 | @REM install vscode extension 10 | code --install-extension ms-vscode-remote.vscode-remote-extensionpack &^ 11 | code --install-extension amazonwebservices.aws-toolkit-vscode &^ 12 | code --install-extension alefragnani.project-manager &^ 13 | code --install-extension pengzhanzhao.ec2-farm 14 | echo finish 15 | -------------------------------------------------------------------------------- /setup/vscode/vscode_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // default terminal 3 | "terminal.integrated.profiles.linux": { 4 | "bash": { 5 | "path": "/bin/bash" 6 | } 7 | }, 8 | // notebook 9 | "notebook.formatOnSave.enabled": true, 10 | "notebook.codeActionsOnSave": { 11 | "notebook.source.fixAll": "explicit", 12 | "notebook.source.organizeImports": "explicit" 13 | }, 14 | // python 15 | "[python]": { 16 | "editor.formatOnSave": true, 17 | "editor.defaultFormatter": "charliermarsh.ruff", 18 | "editor.codeActionsOnSave": { 19 | "source.fixAll": "explicit", // fix lint violations on-save 20 | "source.organizeImports": "explicit" // organize imports on-save 21 | } 22 | }, 23 | "mypy-type-checker.args": [ 24 | "--ignore-missing-imports", 25 | "--disallow-untyped-defs" 26 | ], 27 | "python.defaultInterpreterPath": "/opt/pytorch/bin/python", // pytorch env in ec2-ml-ami 28 | "python.analysis.typeCheckingMode": "basic", 29 | "python.analysis.inlayHints.functionReturnTypes": true, 30 | "python.analysis.inlayHints.variableTypes": true, 31 | "python.analysis.completeFunctionParens": true, 32 | // visibility 33 | "editor.bracketPairColorization.enabled": true, 34 | "editor.guides.bracketPairs": "active", 35 | // markdown 36 | "[markdown]": { 37 | "editor.wordWrap": "bounded", 38 | "editor.defaultFormatter": "esbenp.prettier-vscode" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /setup/vscode/vscode_vm_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # prompt for name and email 3 | read -p "Enter your name: " NAME 4 | read -p "Enter your email: " MAIL 5 | 6 | # git 7 | git config --global user.name "$NAME" 8 | git config --global user.email "$MAIL" 9 | git config --global core.editor vim 10 | 11 | # codecommit credential 12 | git config --global credential.helper '!aws codecommit credential-helper $@' 13 | git config --global credential.UseHttpPath true 14 | 15 | # install vscode extension 16 | ## python 17 | code --install-extension ms-python.python 18 | code --install-extension ms-python.vscode-pylance 19 | code --install-extension ms-python.mypy-type-checker 20 | code --install-extension charliermarsh.ruff 21 | code --install-extension donjayamanne.python-extension-pack 22 | ## docker 23 | code --install-extension ms-azuretools.vscode-docker 24 | ## jupyter 25 | code --install-extension ms-toolsai.jupyter 26 | code --install-extension ms-toolsai.jupyter-keymap 27 | code --install-extension ms-toolsai.jupyter-renderers 28 | ## git 29 | code --install-extension mhutchie.git-graph 30 | code --install-extension eamodio.gitlens 31 | code --install-extension donjayamanne.git-extension-pack 32 | ## markdown 33 | code --install-extension yzhang.markdown-all-in-one 34 | code --install-extension shd101wyy.markdown-preview-enhanced 35 | code --install-extension esbenp.prettier-vscode 36 | ## shell 37 | code --install-extension mads-hartmann.bash-ide-vscode 38 | code --install-extension timonwong.shellcheck 39 | code --install-extension foxundermoon.shell-format 40 | ## visibility 41 | code --install-extension mechatroner.rainbow-csv 42 | code --install-extension GrapeCity.gc-excelviewer 43 | code --install-extension janisdd.vscode-edit-csv 44 | code --install-extension monokai.theme-monokai-pro-vscode 45 | code --install-extension vscode-icons-team.vscode-icons 46 | code --install-extension MS-CEINTL.vscode-language-pack-ja 47 | ## other 48 | code --install-extension github.copilot 49 | code --install-extension github.copilot-chat 50 | code --install-extension amazonwebservices.aws-toolkit-vscode 51 | code --install-extension amazonwebservices.amazon-q-vscode 52 | code --install-extension saoudrizwan.claude-dev 53 | 54 | # vscode settings 55 | cp vscode_settings.json ~/.vscode-server/data/Machine/settings.json 56 | 57 | echo finish 58 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ren8k/aws-ec2-devkit-vscode/0197763362d040eb0dfe7ef31cddded3877a9f5b/src/__init__.py -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | def main() -> None: 2 | print("Hello, World!") 3 | 4 | 5 | if __name__ == "__main__": 6 | main() 7 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.13" 4 | 5 | [[package]] 6 | name = "app" 7 | version = "0.1.0" 8 | source = { editable = "." } 9 | --------------------------------------------------------------------------------