In this post:
- example configuration
- command line breakdowns
- links to relevant documentation
I recently set up containerised builds for my website [It’s not quite ready yet.] and thought I’d share the configuration for others to use as reference.
💁♂️ Note that I’m using Docker mainly to avoid installing tooling globally. If this isn’t the case for you, then a different build strategy will likely be better.
Additionally, some command lines will contain placeholders with example content {EX:like this} and optional segments [OPT:like this]. You will have to at least remove the respective parentheses and EX: or OPT: to make them work.
.vscode/tasks.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format¹
"version": "2.0.0",
"tasks": [
{
"label": "Create {EX:target/bundle/schichler-dev}/",
"type": "shell",
"command": "mkdir --parents {EX:target/bundle/schichler-dev}",
"windows": {
"command": "if not exist {EX:target/bundle/schichler-dev}/NUL mkdir {EX:target\\bundle\\schichler-dev}"
}
},
{
"label": "Build {EX:schichler-dev}",
"dependsOn": [
"Create {EX:target/bundle/schichler-dev}/"
],
"type": "shell",
"command": "docker build -t {EX:schichler-dev} -f {EX:schichler-dev/Dockerfile} {EX:.} && docker run [OPT:--read-only] --mount type=bind,source=${workspaceFolder}{EX:/target/bundle/schichler-dev},destination=/mnt/target --rm {EX:schichler-dev}",
// The task group shown by Tasks: Run Build Task.
"group": "build",
"presentation": {
// Automatically show the problems panel if any problems are matched.
// The default here is "never".
"revealProblems": "onProblem"
},
// Prevents Code's prompt whether to show output.
// This was added automatically when I selected never to.
// You can add problem matchers² to make Code recognise
"problemMatcher": []
}
]
}
¹ Integrate with External Tools via Tasks; comment from default tasks.json.
² See # Processing task output with problem matchers.
This creates the following entry in the Tasks: Run Build Task command menu, by default bound to Ctrl + Shift + B:
![[Select the build task to run] > Build schichler-dev](/assets/img/posts/2020-02-27-Building non containers with Docker and VS Code/run task Build schichler-dev.png)
…which runs the following shell commands in dependent sequence:
1
2
docker build -t {EX:schichler-dev} -f {EX:schichler-dev/Dockerfile} {EX:.}
docker run [OPT:--read-only] --mount type=bind,source=${workspaceFolder}{EX:/target},destination=/mnt/target --rm {EX:schichler-dev}
In my case:
- Make the directory (
mkdir) path (--parents)target/bundle/schichler-dev, if it doesn’t exist yet (--parents).
💁♂️ Windows requires special handling here, since Windows’s MKDIR will error if the directory already exists, isn’t configurable in that regard, and also doesn’t support/as path separator.
CMD /E:ON /Cmakes sure command extensions are on (default since 2000/XP) so we can create the entire path at once.
if not exist target/bundle/schichler-dev/NULmakes suretarget/bundle/schichler-devdoesn’t exist as a directory already, by checking for the special fileNULwithin it.
See https://stackoverflow.com/a/4165472. 2.- Build a Docker image and tag (
-t) it asschichler-dev(:latest).
Use the Docker file (-f) located atschichler-dev/Dockerfile³ and use.⁴ as context root. - Run the Docker image tagged
schichler-devwith its internal file system read-only (--read-only)⁵, while mounting (--mount)${workspaceFolder}/target/bundle/schichler-dev⁶ mutably inside the container as/mnt/target. Remove (--rm) the container instance afterwards.
- Build a Docker image and tag (
³ You don’t need to specify this for a Dockerfile in the context root.
⁴ The folder opened in Code is the working directory for the command.
⁵ This isn’t strictly necessary, but Docker may be able to start the container a little faster if it has a matching optimisation.
⁶ Full paths are required here.
💁♂️ Code handily expands ${workspaceFolder} to what we need. Show the suggestions (default: Ctrl + Space) within the "command" parameter’s value (but only before the first such expansion, it seems) for a list of other values that can be interpolated.
Dockerfile
End your (Unix) Dockerfile with:
1
2
CMD rm -fr /mnt/target/* \
&& cp -vr --no-target-directory {EX:bundle} /mnt/target
This in my case:
Removes (
rm), recursively (-r), all files and directories (*) inside the mounted host directory.Copies (
cp), recursively (-r), the contents of (--no-target-directory) my build directory inside the container (bundle) into the mounted host directory visible at/mnt/targetinside the container.
💁♂️ Instead of writing--no-target-directory, you could append/*to the source directory to use shell expansion. I don’t know whether this makes a practical difference.
Running the Task
You can now run the build task by pressing Ctrl + Shift + B and then Enter.
Code should show the output of the command in a new task terminal window.