Skip to content

Commit 1171683

Browse files
committed
added devcontainers
1 parent 2ef1d29 commit 1171683

File tree

3 files changed

+164
-12
lines changed

3 files changed

+164
-12
lines changed

docs/Building-your-own-images/dockerfiles.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ RUN pip install --no-cache-dir \
5151
# Copy the entire project
5252
COPY . .
5353

54-
# Create non-root user for security
55-
RUN useradd -m jupyter && \
56-
chown -R jupyter:jupyter /workspace
57-
USER jupyter
58-
5954
# Expose the port Jupyter will run on
6055
EXPOSE 8888
6156

@@ -104,13 +99,6 @@ Let's walkthrough the Dockerfile.
10499
- Second '.' means copy to current WORKDIR
105100
- Done after requirements for better caching
106101

107-
**`RUN useradd -m jupyter && chown -R jupyter:jupyter /workspace`**
108-
109-
- Creates non-root user 'jupyter' for security
110-
- `-m` creates home directory
111-
- Changes ownership of /workspace to this user
112-
- Best practice: don't run as root
113-
114102
**`USER jupyter`**
115103

116104
- Switches to non-root user

docs/devcontainers.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,165 @@
11
# Devcontainers
2+
In the reproducibility section, we talked about the different levels of reproducibilty. You are probably familiar with things like Python venvs, conda environments, and even virtual machines. These are all ways to isolate your code and dependencies from the rest of your system. But what if you could isolate your code and dependencies in a way that is even more portable and reproducible? That's where devcontainers come in.
3+
4+
The Visual Studio Code Dev Containers extension lets you use a container as a dev environment. You can open any folder inside (or mounted into) a container inside VSCode. A `devcontainer.json` file in your project tells VS Code how to access (or create) a development container with a well-defined tool and runtime stack. This container can be used to run an application or to separate tools, libraries, or runtimes needed for working with a codebase.
5+
6+
Workspace files are mounted from the local file system or copied or cloned into the container. Extensions are installed and run inside the container, where they have full access to the tools, platform, and file system. This means that you can seamlessly switch your entire development environment just by connecting to a different container.
7+
8+
<a>
9+
<img src="../imgs/architecture-containers.png" alt="docker-cont">
10+
</a>
11+
12+
Let's create a bare-bones devcontainer for our python project. Create a new folder:
13+
14+
```bash
15+
mkdir .devcontainer
16+
```
17+
and then create a new file:
18+
```bash
19+
touch .devcontainer/devcontainer.json
20+
```
21+
Now populate it with the following:
22+
```json
23+
{
24+
"name": "Research Environment",
25+
"build": {
26+
"dockerfile": "../Dockerfile",
27+
"context": "."
28+
},
29+
"forwardPorts": [8888]
30+
}
31+
```
32+
This will create a new devcontainer called "Research Environment" that will use the Dockerfile in the parent directory. It will also forward port 8888 to the host machine.
33+
34+
This is very basic. We don't have much functionality here at all. And how do we even access the actual jupyter lab server? We don't even have the python extension installed in the container! We would also find that any changes to the the stuff inside the container would not be reflected in the host machine. So let's make our experience more enjoyable.
35+
36+
```json
37+
{
38+
"name": "Research Environment",
39+
"build": {
40+
"dockerfile": "../Dockerfile",
41+
"context": ".."
42+
},
43+
44+
// Features to add to the dev container
45+
"features": {
46+
"ghcr.io/devcontainers/features/git:1": {}
47+
},
48+
49+
// Configure tool-specific properties
50+
"customizations": {
51+
"vscode": {
52+
"extensions": [
53+
"ms-python.python",
54+
"ms-python.vscode-pylance",
55+
"ms-python.black-formatter",
56+
"ms-toolsai.jupyter",
57+
"github.copilot"
58+
],
59+
"settings": {
60+
"python.defaultInterpreterPath": "/usr/local/bin/python",
61+
"python.linting.enabled": true,
62+
"python.formatting.provider": "black",
63+
"editor.formatOnSave": true,
64+
"editor.rulers": [88]
65+
}
66+
}
67+
},
68+
69+
// Use 'forwardPorts' to make a list of ports inside the container available locally
70+
"forwardPorts": [8888],
71+
72+
// Run commands after container is created
73+
"postCreateCommand": "pip install -r requirements.txt",
74+
75+
// Set environment variables
76+
"remoteEnv": {
77+
"PYTHONPATH": "${containerWorkspaceFolder}"
78+
},
79+
}
80+
```
81+
82+
Now we have **a lot** more functionality!
83+
84+
Let's look at exactly what is going on here:
85+
86+
1. Top-level configuration:
87+
```json
88+
"name": "Research Environment",
89+
```
90+
This simply names your development container for easy identification.
91+
92+
2. Build configuration:
93+
```json
94+
"build": {
95+
"dockerfile": "../Dockerfile",
96+
"context": ".."
97+
}
98+
```
99+
This tells VS Code how to build the container:
100+
- `dockerfile`: Points to a Dockerfile one directory up from the devcontainer.json
101+
- `context`: Sets the build context to the parent directory - what stuff to include in the build
102+
103+
3. Features section:
104+
```json
105+
"features": {
106+
"ghcr.io/devcontainers/features/git:1": {}
107+
}
108+
```
109+
This adds additional tools to your container. Here, it's installing Git from the GitHub Container Registry.
110+
111+
4. VS Code Customizations:
112+
```json
113+
"customizations": {
114+
"vscode": {
115+
"extensions": [...],
116+
"settings": {...}
117+
}
118+
}
119+
```
120+
This configures VS Code-specific settings:
121+
- Extensions installed automatically:
122+
- Python extension
123+
- Pylance (Python language server)
124+
- Black formatter
125+
- Jupyter notebook support
126+
- GitHub Copilot
127+
- VS Code settings configured:
128+
- Sets Python interpreter path
129+
- Enables linting
130+
- Uses Black for formatting
131+
- Enables format-on-save
132+
- Sets a line length ruler at 88 characters (Black's default)
133+
134+
We can add other dev tools here like mypy or itools or flake8.
135+
136+
1. Port Forwarding:
137+
```json
138+
"forwardPorts": [8888]
139+
```
140+
Makes port 8888 (commonly used for Jupyter notebooks) available on your local machine.
141+
142+
1. Post-Creation Commands:
143+
```json
144+
"postCreateCommand": "pip install -r requirements.txt"
145+
```
146+
Runs after the container is created - in this case, installing Python dependencies from requirements.txt.
147+
148+
1. Environment Variables:
149+
```json
150+
"remoteEnv": {
151+
"PYTHONPATH": "${containerWorkspaceFolder}"
152+
}
153+
```
154+
Sets environment variables in the container:
155+
- Adds the workspace folder to Python's module search path, letting you import from any subdirectory
156+
157+
This configuration creates a fully-featured Python development environment with:
158+
- Code formatting and linting
159+
- Jupyter notebook support
160+
- Git integration
161+
- Automatic dependency installation
162+
- Proper Python path configuration
163+
- AI assistance through Copilot
164+
165+
We are also free to add other features such as poetry.
11 KB
Loading

0 commit comments

Comments
 (0)