Skip to content

Commit 936b93c

Browse files
Update docker
1 parent ab4b053 commit 936b93c

File tree

6 files changed

+128
-10
lines changed

6 files changed

+128
-10
lines changed

building/config.json

+7
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,13 @@
717717
"title": "Tooling Docker Setup",
718718
"blurb": ""
719719
},
720+
{
721+
"uuid": "83dc65b9-cc74-4a2a-9c70-472f6416c19d",
722+
"slug": "tooling/best-practices",
723+
"path": "building/tooling/best-practices.md",
724+
"title": "Best Practices",
725+
"blurb": ""
726+
},
720727
{
721728
"uuid": "b080e814-d3b9-4027-a25e-907f5505cf8d",
722729
"slug": "tooling/analyzers",

building/tooling/analyzers/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ You can use the following documents to learn more about building an analyzer:
2121
- [Writing Analyzer comments](/docs/building/tooling/analyzers/comments)
2222
- [Tagging solutions](/docs/building/tooling/analyzers/tags)
2323
- [Guidance for building an Analyzer](/docs/building/tooling/analyzers/guidance)
24+
- [Best practices](/docs/building/tooling/best-practices)

building/tooling/best-practices.md

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Best Practices
2+
3+
## Follow best practices
4+
5+
The official [Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) have lots of great content on how to improve your Dockerfiles.
6+
7+
## Prefer official images
8+
9+
There are many Docker images on [Docker Hub](https://hub.docker.com/), but try to use [official ones](https://hub.docker.com/search?q=&image_filter=official).
10+
11+
## Pin versions
12+
13+
To ensure that builds are stable (i.e. they don't suddenly break), you should always pin your base images to specific tags.
14+
That means instead of:
15+
16+
```dockerfile
17+
FROM alpine:latest
18+
```
19+
20+
you should use:
21+
22+
```dockerfile
23+
FROM alpine:3.20.2
24+
```
25+
26+
With the latter, builds will always use the same version.
27+
28+
## Performance
29+
30+
You should primarily optimize for performance (especially for test runners).
31+
This will ensure your tooling runs as fast as possible and does not time-out.
32+
33+
### Experiment with different Base images
34+
35+
Try experimenting with different base images (e.g. Ubuntu instead of Alpine), to see if one (significantly) outperforms the other.
36+
If performance is relatively equal,
37+
38+
### Try Internal Network
39+
40+
Check if using the `internal` network instead of `none` improves performance.
41+
See the [network docs](/docs/building/tooling/docker#network) for more information.
42+
43+
### Prefer build-time commands over run-time commands
44+
45+
Tooling runs as one-off, short-lived Docker container:
46+
47+
1. A Docker container is created
48+
2. The Docker container is run with the correct arguments
49+
3. The Docker container is destroyed
50+
51+
Therefore, code that runs in step 2 runs for _every single tooling run_.
52+
For this reason, reducing the amount of code to run in step 2 is a great way to improve performance
53+
One way of doing this is to move code from _run-time_ to _build-time_.
54+
Whilst run-time code runs every single tooling run, build_time code only runs once (when the Docker image is built).
55+
56+
As build-time code runs as part of a GitHub Actions workflow, the student will never notice it.
57+
This also means that the code at build-time could be relatively slow, it's only running once after all!
58+
59+
## Size
60+
61+
You should try to reduce the image's size, which means that it'll be:
62+
63+
- Faster to deploy
64+
- Reduces costs for us
65+
- Marginally improves startup time of each container
66+
67+
### Try different Base images
68+
69+
Some base images are
70+
71+
### Removing unneeded bits
72+
73+
An obvious, but great, way to reduce the size of your image is to remove anything you don't need.
74+
These can include things like:
75+
76+
- Source files that are no longer needed after building a binary from them
77+
- Files targeting different architectures from the Docker image
78+
- Documentation
79+
80+
### Cleanup package manager
81+
82+
### Use multi-stage builds
83+
84+
https://docs.docker.com/build/building/multi-stage/
85+
86+
TODO
87+
88+
## Safety
89+
90+
TODO
91+
92+
## Support read-only filesystem
93+
94+
TODO

building/tooling/docker.md

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
# Tooling Docker Setup
1+
# Docker Setup
22

33
Our various track tooling are deployed as Docker images.
44

5-
Each piece of tooling requires a Dockerfile, which specifies how the machine is built.
5+
Each piece of tooling requires a [Dockerfile](https://docs.docker.com/reference/dockerfile/), which specifies how the machine is built.
66
It should live at the root directory of your repository and should be called `Dockerfile`.
77

88
The Dockerfile should create the minimal image needed for the tooling to function correctly and speedily.
9-
10-
The Dockerfile should produce an image with as a small a size as possible while maximizing (and prioritizing) performance.
11-
Applying the official [Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) can help to create a minimal image.
9+
Our [Best Practices page](/docs/building/tooling/best-practices) has lots of tips to help you achieve this goal.
1210

1311
## Execution
1412

@@ -20,15 +18,15 @@ At the end of that period it will be timed out with a 408 error code.
2018
### Stdout/stderr
2119

2220
A tooling run may produce up to a maximum of one-megabyte of stdout and stderr.
23-
If it produces more it will be killed with a 413 error code.
21+
If it produces more, it will be killed with a 413 error code.
2422

2523
The contents of `stdout` and `stderr` from each run will be stored in files that can be viewed later.
2624

27-
You may write an `results.out` file to the output directory, which contains debugging information you want to later view.
25+
You may write a `results.out` file to the output directory, which contains debugging information you want to view later.
2826

2927
### Results
3028

31-
The results file may be no larger than 500 kilobytes (including any stack traces etc).
29+
The results file may not be larger than 500 kilobytes (including any stack traces etc).
3230
If the file is larger than this, the tooling run will be killed with a 460 error code.
3331

3432
## Configuration
@@ -37,7 +35,8 @@ Each solution gets 100% machine resources for a twenty second window.
3735

3836
After 20 seconds, the process is halted and reports as a time-out.
3937

40-
Configuration can be set in the [`tools.json` file](https://github.com/exercism/tooling-invoker/blob/main/tools.json) in the Tooling Invoker repository.
38+
Some tools require (slight) deviations from the default configuration.
39+
If so, these are configured in the [`tools.json` file](https://github.com/exercism/tooling-invoker/blob/main/tools.json) in the Tooling Invoker repository.
4140

4241
### Network
4342

@@ -51,6 +50,21 @@ Different languages perform better/worse with different configurations (e.g. Rub
5150
You can experiment locally by using the `--network` flag when running your docker. `--network none` is supported by default.
5251
To use the internal network, first run `docker network create --internal internal` to create the network, then use `--network internal` when running the container.
5352

53+
### Read-only filesystem
54+
55+
We encourage Docker files to be written using a read-only filesystem.
56+
The only directories you should assume to be writeable are:
57+
58+
- The solution dir (passed in as the second argument)
59+
- The output dir (passed in as the third argument)
60+
- The `/tmp` dir
61+
62+
```exercism/caution
63+
Our production environment currently does _not_ enforce a read-only filesystem, but we might in the future.
64+
For this reason, the base template for a new test runner/analyzer/representer starts out with a read-only filesystem.
65+
If you can't get things working on a read-only file, feel free to (for now) assume a writeable file system.
66+
```
67+
5468
### Memory
5569

5670
Languages can set the maximum memory they need to use to run their jobs. Setting this to be as low as possible means that we can run more jobs more quickly in parallel. It also means that people who try and abuse memory will not be able to succeed. Different languages need wildly different maximum memory usage. Benchmarking the execution of a docker run to establish the maximum memory it uses is advised and appreciated.
@@ -67,4 +81,4 @@ docker container run -v /path/to/job:/mnt/exercism-iteration --network none -m 1
6781

6882
## Editing a Dockerfile
6983

70-
All changes to Dockerfiles require a PR review from the @exercism/ops team, in order to avoid the introduction of security exploits.
84+
All changes to Dockerfiles require a PR review from the `@exercism/maintainers-admin` team, in order to avoid the introduction of security exploits.

building/tooling/representers/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ You can use the following documents to learn more about building a representer:
3535
- [The Representer interface](/docs/building/tooling/representers/interface)
3636
- [How to normalize representations for the highest efficiency](/docs/building/tooling/representers/normalization)
3737
- [How to build a Docker image with Docker for local testing and deployment](/docs/building/tooling/representers/docker)
38+
- [Best practices](/docs/building/tooling/best-practices)

building/tooling/test-runners/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ You can use the following documents to learn more about building a test runner:
2323
- [creating a Test Runner from scratch](/docs/building/tooling/test-runners/creating-from-scratch)
2424
- [The Test Runner interface](/docs/building/tooling/test-runners/interface)
2525
- [How to build a Docker image with Docker for local testing and deployment](/docs/building/tooling/test-runners/docker)
26+
- [Best practices](/docs/building/tooling/best-practices)

0 commit comments

Comments
 (0)