Cookiecutter-django: VS Code Dev Container setup

Created on 30 Apr 2020  路  3Comments  路  Source: pydanny/cookiecutter-django

Description

Hi,

I spent some time today setting up vs code with "dev container" to work with cookiecutter-django. At the end the dev experience is pretty good as you can code seemlessly directly from within the "django" container with the python interpreter linting and everything coming from the container.

I will share here my setup but it can definetly be improved and added to cookiecutter-django. I did the following things:

  • install git, zsh and ohmyzsh inside the container when vs code is attaching to it.
  • add python, and intellicode extensions when vs code attach to the container.
  • setup linting, formatting and testing to work out of the box when attaching to the container.
  • override the docker-compose to add a custom .zshrc volume which export the missing ENV variable.

Rationale

Better DX on VS Code using dev container.

Use case(s) / visualization(s)

Once the project created, I just added a .devcontainer folder at the root of my project with the following files:

A devcontainer.json to set what happens when vs code is attaching to the container:

// devcontainer.json
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/docker-existing-docker-compose
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
  "name": "Existing Docker Compose (Extend)",
  // Update the 'dockerComposeFile' list if you have more compose files or use different names.
  // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
  "dockerComposeFile": ["../local.yml", "./docker-compose.override.yml"],
  // The 'service' property is the name of the service for the container that VS Code should
  // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
  "service": "django",
  // The optional 'workspaceFolder' property is the path VS Code should open by default when
  // connected. This is typically a file mount in .devcontainer/docker-compose.yml
  "workspaceFolder": "/app",
  // Set *default* container specific settings.json values on container create.
  "settings": {
    "terminal.integrated.shell.linux": "/bin/zsh",
    "[python]": {
      "editor.rulers": [120]
    },
    "editor.formatOnSave": true,
    "python.pythonPath": "/usr/local/bin/python",
    "python.linting.pylintEnabled": true,
    "python.formatting.provider": "black",
    "python.linting.flake8Enabled": true,
    "python.linting.mypyEnabled": true
  },
  // Add the IDs of extensions you want installed when the container is created.
  "extensions": [
    "ms-python.python",
    "visualstudioexptteam.vscodeintellicode",
    "esbenp.prettier-vscode"
  ],
  // Uncomment the next line if you want start specific services in your Docker Compose config.
  // "runServices": [],
  // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
  // "shutdownAction": "none",
  // Uncomment the next line to run commands after the container is created - for example installing git.
  "postCreateCommand": "apt-get update && apt-get install -y git zsh wget && wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh || true"
  // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
  // "remoteUser": "vscode"
}

a new .zshrc for adding the missing env variable to the shell:

# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# Path to your oh-my-zsh installation.
export ZSH="/root/.oh-my-zsh"

# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
ZSH_THEME="robbyrussell"

# Set list of themes to pick from when loading at random
# Setting this variable when ZSH_THEME=random will cause zsh to load
# a theme from this variable instead of looking in ~/.oh-my-zsh/themes/
# If set to an empty array, this variable will have no effect.
# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" )

# Uncomment the following line to use case-sensitive completion.
# CASE_SENSITIVE="true"

# Uncomment the following line to use hyphen-insensitive completion.
# Case-sensitive completion must be off. _ and - will be interchangeable.
# HYPHEN_INSENSITIVE="true"

# Uncomment the following line to disable bi-weekly auto-update checks.
# DISABLE_AUTO_UPDATE="true"

# Uncomment the following line to automatically update without prompting.
# DISABLE_UPDATE_PROMPT="true"

# Uncomment the following line to change how often to auto-update (in days).
# export UPDATE_ZSH_DAYS=13

# Uncomment the following line if pasting URLs and other text is messed up.
# DISABLE_MAGIC_FUNCTIONS=true

# Uncomment the following line to disable colors in ls.
# DISABLE_LS_COLORS="true"

# Uncomment the following line to disable auto-setting terminal title.
# DISABLE_AUTO_TITLE="false"

# Uncomment the following line to enable command auto-correction.
# ENABLE_CORRECTION="true"

# Uncomment the following line to display red dots whilst waiting for completion.
# COMPLETION_WAITING_DOTS="true"

# Uncomment the following line if you want to disable marking untracked files
# under VCS as dirty. This makes repository status check for large repositories
# much, much faster.
# DISABLE_UNTRACKED_FILES_DIRTY="true"

# Uncomment the following line if you want to change the command execution time
# stamp shown in the history command output.
# You can set one of the optional three formats:
# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
# or set a custom format using the strftime function format specifications,
# see 'man strftime' for details.
# HIST_STAMPS="mm/dd/yyyy"

# Would you like to use another custom folder than $ZSH/custom?
# ZSH_CUSTOM=/path/to/new-custom-folder

# Which plugins would you like to load?
# Standard plugins can be found in ~/.oh-my-zsh/plugins/*
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(git)

source $ZSH/oh-my-zsh.sh

# User configuration

# export MANPATH="/usr/local/man:$MANPATH"

# You may need to manually set your language environment
# export LANG=en_US.UTF-8

# Preferred editor for local and remote sessions
# if [[ -n $SSH_CONNECTION ]]; then
#   export EDITOR='vim'
# else
#   export EDITOR='mvim'
# fi

# Compilation flags
# export ARCHFLAGS="-arch x86_64"

# Set personal aliases, overriding those provided by oh-my-zsh libs,
# plugins, and themes. Aliases can be placed here, though oh-my-zsh
# users are encouraged to define aliases within the ZSH_CUSTOM folder.
# For a full list of active aliases, run `alias`.
#
# Example aliases
# alias zshconfig="mate ~/.zshrc"
# alias ohmyzsh="mate ~/.oh-my-zsh"

# env variable for django cookiecutter
export CELERY_BROKER_URL="${REDIS_URL}"

if [ -z "${POSTGRES_USER}" ]; then
    base_postgres_image_default_user='postgres'
    export POSTGRES_USER="${base_postgres_image_default_user}"
fi
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"

and finally the docker-compose.override.yml:

version: "3.0"

services:
  django:
    volumes:
      - ./.devcontainer/.zshrc:/root/.zshrc

Let me know what you think about this setup

docker enhancement

Most helpful comment

@grll nice setup!

What is your experience with debugging in your setup?

Have you tried the new debugpy integration in the Python extension?
I am currently struggling to make it work. If you have any tips could you share them please?

Thanks!

All 3 comments

@grll Thank you for putting this together. I haven't used devcontainers before, and I was wondering how is the development experience improved.

there are several development improvement by using this approach. The fact that the IDE is within the container means that you don't need to work with potentially slow mounted volumes, most importantly all the IDE related experience can now be encapsulated within the container and easily shared with your colleagues on a project bases (prettier, pylint, the python interpreter ...) so you not only share the code for the project but also the complete environment to work with the code

@grll nice setup!

What is your experience with debugging in your setup?

Have you tried the new debugpy integration in the Python extension?
I am currently struggling to make it work. If you have any tips could you share them please?

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

webyneter picture webyneter  路  3Comments

linuxluigi picture linuxluigi  路  3Comments

audreyfeldroy picture audreyfeldroy  路  4Comments

sebastian-code picture sebastian-code  路  4Comments

webyneter picture webyneter  路  4Comments