Skip to content

Commit 11e18f2

Browse files
Merge branch 'devcontainers:gh-pages' into gh-pages
2 parents d6ced54 + e57ffdb commit 11e18f2

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

_data/collection-index.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,13 @@
298298
contact: https://github.com/trunk-io/devcontainer-feature/issues
299299
repository: https://github.com/trunk-io/devcontainer-feature
300300
ociReference: ghcr.io/trunk-io/devcontainer-feature
301+
- name: MultiversX Dev Container Templates
302+
maintainer: MultiversX
303+
contact: https://github.com/multiversx/mx-template-devcontainers/issues
304+
repository: https://github.com/multiversx/mx-template-devcontainers
305+
ociReference: ghcr.io/multiversx/mx-template-devcontainers
306+
- name: jemalloc
307+
maintainer: Joseph Heck
308+
contact: https://github.com/heckj/jemalloc/issues
309+
repository: https://github.com/heckj/jemalloc
310+
ociReference: ghcr.io/heckj/jemalloc

_posts/2023-02-15-gitlab-ci.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
layout: post
3+
title: "Working with GitLab CI"
4+
author: "@raginjason"
5+
authorUrl: https://github.com/raginjason
6+
---
7+
8+
For simple use cases you can use your development container (dev container) for CI without much issue. Once you begin using more advanced dev container functionality such as [Features](/features), you will need dev container tooling in your CI pipeline. While GitHub CI has the [devcontainers-ci GitHub Action](https://github.com/marketplace/actions/devcontainers-ci), there is no such analog in GitLab CI. To achieve the goal of using your dev container in GitLab CI, the container must be pre-built.
9+
10+
This document will guide you on how to build a dev container with GitLab CI, push that dev container to the GitLab Container Registry, and finally reference that dev container in your main project for both local development and GitLab CI.
11+
12+
For the purpose of this document, we will assume the main project is named `my-project` and lives under the `my-user` path. The example here uses a few [Features](/features), which is what forces the container to be pre-built.
13+
14+
## <a href="#dev-container-project" name="dev-container-project" class="anchor">The Development Container GitLab project</a>
15+
16+
Create a project in GitLab where the stand-alone dev container project will live. As the main project is assumed to be named `my-project`, let's assume the dev container project name will be `my-project-dev-container`
17+
18+
### <a href="#dev-container-json" name="dev-container-json" class="anchor">Development Container .devcontainer/devcontainer.json</a>
19+
20+
The example here is a CDK project for Python makes use of both the [AWS CLI](https://github.com/devcontainers/features/tree/main/src/aws-cli) and the community-maintained [AWS CDK](http://github.com/devcontainers-contrib/features/tree/main/src/aws-cdk) Features.
21+
22+
`.devcontainer/devcontainer.json`:
23+
24+
```json
25+
{
26+
"build": {
27+
"context": "..",
28+
"dockerfile": "Dockerfile"
29+
},
30+
"features": {
31+
"ghcr.io/devcontainers/features/aws-cli:1": {},
32+
"ghcr.io/devcontainers-contrib/features/aws-cdk:2": {}
33+
},
34+
"customizations": {
35+
"vscode": {
36+
"settings": {
37+
"python.formatting.provider": "black"
38+
}
39+
}
40+
}
41+
}
42+
```
43+
44+
### <a href="#dev-container-dockerfile" name="dev-container-dockerfile" class="anchor">Development Container Dockerfile</a>
45+
46+
As this is a Python project working with CDK, the `Dockerfile` will begin by using the latest Python dev container image and then install some basic packages via `pip`.
47+
48+
`Dockerfile`:
49+
50+
```Dockerfile
51+
FROM mcr.microsoft.com/devcontainers/python:latest
52+
53+
RUN pip3 --disable-pip-version-check --no-cache-dir install aws_cdk_lib constructs jsii pylint \
54+
&& rm -rf /tmp/pip-tmp
55+
```
56+
57+
### <a href="#dev-container-gitlab-ci" name="dev-container-gitlab-ci" class="anchor">Development Container .gitlab-ci.yml</a>
58+
59+
Since there is no GitLab CI equivalent to [devcontainers-ci GitHub Action](https://github.com/marketplace/actions/devcontainers-ci), we will need to install the devcontainers CLI manually. The following will:
60+
61+
1. Install the packages that the devcontainers CLI requires
62+
2. Install the devcontainers CLI itself
63+
3. Login to GitLab Container Repository
64+
4. Build the dev container and push it to the GitLab Container Repository
65+
66+
`.gitlab-ci.yml`:
67+
68+
```yaml
69+
image: docker:latest
70+
71+
variables:
72+
DOCKER_TLS_CERTDIR: "/certs"
73+
74+
services:
75+
- docker:dind
76+
77+
before_script:
78+
- apk add --update nodejs npm python3 make g++
79+
- npm install -g @devcontainers/cli
80+
81+
build:
82+
stage: build
83+
script:
84+
- docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
85+
- devcontainer build --workspace-folder . --push true --image-name ${CI_REGISTRY_IMAGE}:latest
86+
```
87+
88+
## <a href="#main-project" name="main-project" class="anchor">The Main GitLab project</a>
89+
90+
### <a href="#main-project-devcontainer-json" name="main-project-devcontainer-json" class="anchor">Main .devcontainer/devcontainer.json</a>
91+
92+
`.devcontainer/devcontainer.json`:
93+
94+
```json
95+
{
96+
"image": "registry.gitlab.com/my-user/my-project-dev-container"
97+
}
98+
```
99+
100+
### <a href="#main-project-gitlab-ci-json" name="main-project-gitlab-ci-json" class="anchor">Main .gitlab.ci.yml</a>
101+
102+
Assuming the dev container project name is based off the main project name, the `${CI_REGISTRY_NAME}` variable can be used. This configuration performs some basic sanity checks and linting once merge requests are submitted.
103+
104+
`.gitlab-ci.json`:
105+
106+
```yaml
107+
image: ${CI_REGISTRY_IMAGE}-dev-container:latest
108+
109+
before_script:
110+
- python --version
111+
- cdk --version
112+
113+
stages:
114+
- Build
115+
- Lint
116+
117+
py_compile:
118+
stage: Build
119+
script:
120+
- find . -type f -name "*.py" -print | xargs -n1 python3 -m py_compile
121+
rules:
122+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
123+
124+
cdk synth:
125+
stage: Build
126+
script:
127+
- JSII_DEPRECATED=fail cdk --app "python3 app.py" synth
128+
rules:
129+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
130+
131+
Pylint:
132+
stage: Lint
133+
script:
134+
- pylint *
135+
rules:
136+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
137+
138+
Black code format:
139+
stage: Lint
140+
script:
141+
- black --check --diff .
142+
rules:
143+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
144+
```
145+
146+
## <a href="#conclusion" name="conclusion" class="anchor">Conclusion</a>
147+
148+
It's worth noting that the best practice would be to pin the versions of the various packages installed by `pip`, `apk`, `npm` and the like. Version pinning was omitted from this guide so that it can be executed as-is without issue.
149+
150+
The above provides a starting point for a dev container that's used for both local development and in GitLab CI. It can easily be customized for other languages and tool chains. Take it and make it your own, happy coding!

0 commit comments

Comments
 (0)