Deploying Mailcow Mail Server Offline Using Docker Compose
To deploy Mailcow in a restricted network environment without internet access, such as an isolated internal network, follow this process to export and import Docker images.
Prerequisites
- A new environment with Docker installed and running, meeting Mailcow's version requirements.
- An existing Mailcow installation with all Docker images intact.
- The image verisons used here align with a standard Mailcow containerized deployment.
Exporting Docker Images
List the Docker images associated with Mailcow on the source server:
docker images
Save the image list to a file:
docker images > image_list.txt
Create a script to export each image as a tar archive:
cat image_list.txt | awk 'BEGIN{print "#!/bin/bash"} $1 != "REPOSITORY" {print "docker save "$3">"$3".tar"}' > export_images.sh
Example script content:
#!/bin/bash
docker save 936dbfa3fd1a>936dbfa3fd1a.tar
docker save f9d025710983>f9d025710983.tar
# Additional lines for each image
Run the script to generate tar files in a backup directory:
sh export_images.sh
Verify the exported files:
ls -lh *.tar
Transferring Files
Copy the exported tar files, image_list.txt, and the mailcow-dockerized directory (containing docker-compose.yml) to the target server.
Importing Docker Images
On the target server, create a script to load images and tag them appropriately:
cat image_list.txt | awk 'BEGIN{print "#!/bin/bash"} $1 != "REPOSITORY" {print "docker load < "$3".tar"; print "docker tag "$3" "$1":"$2}' > import_images.sh
Example script content:
#!/bin/bash
docker load < 936dbfa3fd1a.tar
docker tag 936dbfa3fd1a memcached:alpine
docker load < f9d025710983.tar
docker tag f9d025710983 mailcow/phpfpm:1.88
# Additional lines for each image
Execute the import script:
sh import_images.sh
Confirm the images are loaded:
docker images
Starting Containers
Navigate to the Mailcow directory and start the services:
cd mailcow-dockerized
docker compose up -d
Troubleshooting Unbound Health Check
In offline environments, the Unbound container may fail health checks that test external DNS servers and domains. This results in an error like dependency failed to start: container mailcowdockerized-unbound-mailcow-1 is unhealthy.
To resolve, edit mailcow.conf in the Mailcow directory and set:
SKIP_UNBOUND_HEALTHCHECK=y
Alternatively, modify the health check script inside the Unbound container. Access the container:
docker exec -it <unbound_container_id> /bin/bash
Edit /healthcheck.sh, changing all exit 1 commands to exit 0. Run the script manually to update the container status to healthy, then restart the services.