You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**CI/CD secrets automatically available in `moby/demo-app`:**
173
+
**CI/CD secrets automatically available in `moby/demo-app` (unless `SKIP_CI_SECRET_SETUP` is set to
174
+
`true`on the `workspace` service):**
174
175
175
176
| Secret | Value |
176
177
|--------|-------|
@@ -181,6 +182,10 @@ by updating the GitHub Actions publish workflow (`.github/workflows/publish.yml`
181
182
| `DOCKERHUB_PASSWORD` | from user's Docker Desktop |
182
183
| `KUBECONFIG` | pre-generated k3s config |
183
184
185
+
**Note:** If the `SKIP_CI_SECRET_SETUP` environment variable is set on the `workspace` service, all
186
+
CI secret setup will be skipped. Ideally, this is set in the lab's own `compose.override.yaml` file.
187
+
This is helpful in labs in which the student is going to setup the CI secrets themselves.
188
+
184
189
The labspace project files are automatically committed to `moby/demo-app` at startup. If the project
185
190
contains `.gitea/workflows/`, those workflows will automatically run after the initial push.
186
191
@@ -359,7 +364,10 @@ graph TD
359
364
1.**Stay focused** — Keep the labspace to 1–2 core takeaways. More content can always be a new
360
365
labspace.
361
366
362
-
2.**Make it fun** — Use an engaging story or sample application. Creative emojis are encouraged!
367
+
2.**Make it fun** — Use an engaging story or sample application. Emojis are encouraged, but use
368
+
them with taste: a well-placed emoji adds color and personality; too many makes content feel
369
+
cluttered and hard to scan. Good uses include section headings, callouts, and key moments of
370
+
celebration or warning. Avoid sprinkling them into every sentence or bullet point.
363
371
364
372
3.**Empower the student** — Use second-person ("you"), never first-person plural ("we", "us",
365
373
"let's", "our"):
@@ -387,6 +395,40 @@ graph TD
387
395
8.**Verify the environment first** — The first section should always include a simple command
388
396
that confirms the environment is working correctly.
389
397
398
+
9.**Use numbered steps for sequential exercises** — When students must perform a series of
399
+
actions, use a numbered list with each code block indented (4 spaces) so it is nested inside
400
+
its list item. This keeps the command visually tied to its step and makes progress easy to
401
+
track. Never use a wall of text followed by disconnected code blocks for sequential actions.
402
+
403
+
When a step creates or updates a file, include the filename and intent in the step text so
404
+
students have enough context to complete the action even without using the Save button:
405
+
406
+
- ✓ "Create a file named `compose.yaml` with the following contents:"
407
+
- ✓ "Update `compose.yaml` to have the following content:"
408
+
- ❌ "Create the file:" *(which file? what is it?)*
409
+
410
+
````markdown
411
+
1. Create a file named `compose.yaml` with the following contents:
412
+
413
+
```yaml save-as=compose.yaml
414
+
services:
415
+
app:
416
+
image: nginx
417
+
```
418
+
419
+
2. Start it:
420
+
421
+
```bash
422
+
docker compose up -d
423
+
```
424
+
425
+
3. Check that it's running:
426
+
427
+
```bash
428
+
docker ps
429
+
```
430
+
````
431
+
390
432
---
391
433
392
434
## Quality Checklist
@@ -403,6 +445,7 @@ Before finishing, verify:
403
445
-[ ] For SDLC: the note about updating `.github/workflows/publish.yml` is communicated to the user
404
446
-[ ]`project/` contains realistic starter files appropriate to the topic
405
447
-[ ] No instruction or command references `project/` as a path prefix or tells the user to `cd project`
448
+
-[ ] Every step that has users create or update a file clearly states the filename and intent (e.g. "Create a file named `compose.yaml` with the following contents:")
This repository is intended to server as a template to help bootstrap a new Labspace.
3
+
Build a real Node.js API, then containerize every stage of your software development lifecycle — local development, integration testing, CI/CD, and Kubernetes deployment.
4
4
5
-
## Instructions
5
+
## Learning objectives
6
6
7
-
1. Create a new repository using this repo as the template ([docs here](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)).
7
+
This Labspace will have you do the following:
8
8
9
-
**NOTE:** After creating the repo, a GHA workflow will run to do some additional bootstrapping. The bootstrapping workflow file will be removed during bootstrapping.
9
+
- Set up a containerized development environment
10
+
- Use Testcontainers to use containers in integration testing
11
+
- Setup a CI/CD pipeline that will run your tests and build your image
12
+
- Define Kubernetes manifest files
10
13
11
-
2. Clone your newly created repo to your local machine
14
+
## Launch the Labspace
12
15
13
-
3. Start the local development mode:
16
+
To launch the Labspace, run the following command:
14
17
15
-
```bash
16
-
# On Mac/Linux
17
-
CONTENT_PATH=$PWD docker compose up --watch
18
+
```bash
19
+
docker compose -f oci://dockersamples/labspace-containerized-sdlc up -d
20
+
```
18
21
19
-
# On Windows with PowerShell
20
-
$Env:CONTENT_PATH = (Get-Location).Path; docker compose up --watch
21
-
```
22
-
23
-
4. Update the `labspace/labspace.yaml` with your Labspace's title and description
22
+
And then open your browser to http://dockerlabs.xyz.
24
23
25
-
5. Write your Labspace! Being in dev mode, your changes should be visible in the interface without a restart. Feel free to edit either on your host machine or in the Labspace itself!
24
+
### Using the Docker Desktop extension
26
25
27
-
Add any supporting application files or resources directly into the Labspace. This repo will be cloned into the Labspace at startup.
26
+
If you have the Labspace extension installed (`docker extension install dockersamples/labspace-extension` if not), you can also [click this link](https://open.docker.com/dashboard/extension-tab?extensionId=dockersamples/labspace-extension&location=dockersamples/labspace-containerized-sdlc&title=Containerized%20SDLC%20Demo) to launch the Labspace.
28
27
29
-
Be sure to check out the [docs](https://github.com/dockersamples/labspace-infra/tree/main/docs) for additional information and guidelines.
28
+
## Contributing
30
29
30
+
If you find something wrong or something that needs to be updated, feel free to submit a PR. If you want to make a larger change, feel free to fork the repo into your own repository.
31
31
32
+
**Important note:** If you fork it, you will need to update the GHA workflow to point to your own Hub repo.
32
33
33
-
### Setting up the deployment pipeline
34
+
1. Clone this repo
34
35
35
-
The template repo contains a workflow file to make it easy to publish your Labspace.
36
+
2. Start the Labspace in content development mode:
36
37
37
-
1. Add GitHub Action Secrets in your new repo for the following:
38
+
```bash
39
+
# On Mac/Linux
40
+
CONTENT_PATH=$PWD docker compose up --watch
38
41
39
-
- `DOCKERHUB_USERNAME` - the username to authenticate to Docker Hub with
40
-
- `DOCKERHUB_TOKEN` - a personal or organization access token to use for authentication
42
+
# On Windows with PowerShell
43
+
$Env:CONTENT_PATH = (Get-Location).Path; docker compose up --watch
44
+
```
41
45
42
-
2. In the `.github/workflows/publish-labspace.yaml.temp` file, update the `DOCKERHUB_REPO` with the name of the Docker Hub repo you want to publish to.
46
+
3. Open the Labspace at http://dockerlabs.xyz.
43
47
44
-
3. Rename the workflow file to remove the `.temp` extension.
48
+
4. Make the necessary changes and validate they appear as you expect in the Labspace
👋 Welcome to the **Labspace starter** lab! During this lab, you will learn to do the following:
3
+
Welcome to **The Containerized SDLC** lab! By the end, you'll have taken a real Node.js application from a bare source tree all the way through local development, automated testing, a CI/CD pipeline, and a live Kubernetes deployment — with containers playing a starring role at every step.
4
4
5
-
- Learning Objective 1
6
-
- Learning Objective 2
7
-
- Learning Objective 3
8
-
- Learning Objective 4
5
+
## What you'll build
9
6
7
+
**TaskFlow** is a simple task management REST API backed by PostgreSQL. The application code is already written and waiting for you. Your job is to containerize the *process* around it:
10
8
11
-
## 🙋 What is a Labspace again?
9
+
| Stage | What you'll do |
10
+
|---|---|
11
+
| 🖥️ **Local dev**| Write a `compose.yaml` to spin up a database and a visualizer |
12
+
| 🧪 **Testing**| Write integration tests that use Testcontainers to start a real database |
13
+
| 🔄 **CI/CD**| Write a Gitea Actions pipeline that tests, builds, and pushes a container image |
14
+
| ☸️ **Deploy**| Write Kubernetes manifests and deploy to a live k3s cluster |
12
15
13
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis lacinia nisi sit amet auctor accumsan. Maecenas suscipit, libero quis ullamcorper pulvinar, dolor nisl vehicula orci, vel egestas arcu nibh eget enim.
16
+
By the end, you'll see first-hand why a containerized SDLC makes software more portable, consistent, and reproducible.
14
17
15
-
Suspendisse potenti. Pellentesque eleifend eget ante eu egestas.
18
+
## The SDLC journey
16
19
17
-
Nunc sit amet dapibus erat. Aliquam diam arcu, fringilla hendrerit metus sed, pellentesque fringilla lacus.
20
+
```mermaid
21
+
graph LR
22
+
A[🖥️ Local Dev<br>Compose] --> B[🧪 Tests<br>Testcontainers]
23
+
B --> C[🔄 CI/CD<br>Gitea Actions]
24
+
C --> D[☸️ Deploy<br>Kubernetes]
25
+
style A fill:#2563eb,color:#fff
26
+
style B fill:#16a34a,color:#fff
27
+
style C fill:#d97706,color:#fff
28
+
style D fill:#9333ea,color:#fff
29
+
```
18
30
19
-
Nulla ornare nulla risus. Curabitur ut ipsum euismod, accumsan lorem eu, pretium lorem. Fusce imperdiet fermentum hendrerit.
31
+
## Tour the project
20
32
33
+
Start by confirming the environment is ready and getting familiar with the starter code.
21
34
35
+
1. Verify the key tools are available:
36
+
37
+
```bash
38
+
node --version && docker --version && kubectl version --client --short 2>/dev/null || kubectl version --client
39
+
```
40
+
41
+
2. List the project files:
42
+
43
+
```bash
44
+
ls -la
45
+
```
46
+
47
+
You should see `src/`, `package.json`, and `Dockerfile` — the core application that's ready to go.
48
+
49
+
3. Take a quick look at the API in the :fileLink[src/app.js]{path="src/app.js"} file. Specifically, the app:
50
+
51
+
- Exposes three endpoints: `GET /api/tasks`, `POST /api/tasks`, and `DELETE /api/tasks/:id`
This installs Express and the PostgreSQL client (`pg`). It also generates a `package-lock.json` that you'll commit in a later section.
61
+
62
+
5. Try starting the app right now to see what happens without a database:
63
+
64
+
```bash
65
+
node src/app.js
66
+
```
67
+
68
+
> [!NOTE]
69
+
> You'll see something like `Failed to start: connect ECONNREFUSED 127.0.0.1:5432`. The app can't connect to PostgreSQL because there isn't one running yet.
70
+
71
+
That error is exactly the problem you'll solve in the next section. The application needs a database, and the cleanest way to provide one — without installing anything on your machine — is Docker Compose.
0 commit comments