diff --git a/Makefile b/Makefile
index d61687bb53c1761e313c82846e940848b70ca59e..a76884794a15acd44c5df5022e7d40d216fd9dc8 100644
--- a/Makefile
+++ b/Makefile
@@ -83,7 +83,7 @@ endif
 .PHONY: image
 ## image: Run Packer image build : build=<path-to-packer-file>
 image: image-validate
-	packer build -force $(build)
+	packer build -on-error=ask -force $(build)
 
 .PHONY: docker-build
 ## docker-build: Run docker image build for CI and devcontainer
diff --git a/README.md b/README.md
index 604152bbe5fcaeefa633efd75fa5e5d8766bc0ea..90669e451b22fafef842408314b75f0dec04ea42 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ How to deploy UbiCast products:
 - [Installation of required tools](/doc/install.md)
 - [Configuration of the controller and inventory](/doc/config.md)
 - [Deployment of UbiCast softwares](/doc/deploy.md)
-- [Build an image]() (TODO)
+- [Build an image](/doc/image.md)
 
 ## Development
 
diff --git a/doc/image.md b/doc/image.md
new file mode 100644
index 0000000000000000000000000000000000000000..967c86d9ed9a18b2ebbf078930125ea507593f2a
--- /dev/null
+++ b/doc/image.md
@@ -0,0 +1,76 @@
+# Image build
+
+## Requirements
+
+- [Packer](https://packer.io): this is the tool that will automate all the steps of image creation
+- [VMware OVF Tool](https://code.vmware.com/web/tool/4.4.0/ovf): this is required by Packer to export the image from the VMware Hypervisor
+- A running and reachable VMware ESXi Hypervisor
+
+## Prepare Packer file
+
+Copy the example Packer file `packer/example.json`, for example to `packer/mymediaserver.json`, and edit the copied file.
+
+These variable must be configured:
+
+- `variables.name`: used to set the output filename and the machine hostname
+- `variables.esx_*`: VMware hypervisor connection settings
+- `variables.network_*`: used to pre-configure network settings, leave empty to ignore
+- `variables.skyreach_*`: use either `system_key` or `activation_key` and leave the other empty
+
+Then you need the groups that will be applied to the machine, for example for a MediaServer:
+
+```json
+{
+  [...]
+  "provisioners": [
+    [...]
+    {
+      "type": "ansible",
+      [...]
+      "groups": [
+        "monitor",
+        "postgres",
+        "manager",
+        "wowza",
+        "celerity",
+        "server",
+        "import"
+      ]
+    }
+  ]
+}
+```
+
+For a worker:
+
+```json
+{
+  [...]
+  "provisioners": [
+    [...]
+    {
+      "type": "ansible",
+      [...]
+      "groups": [
+        "worker"
+      ]
+    }
+  ]
+}
+```
+
+You can also pass additional variables to ansible in `provisionners['1'].extra_arguments`.
+
+## Build image
+
+Check that the Packer file is valid (the hypervisor must be reachable):
+
+```
+make image-validate build=packer/mymediaserver.json
+```
+
+Build the OVA:
+
+```sh
+make image build=packer/mymediaserver.json
+```