I am trying to compose Apache Guacamole environment with docker-compose file for containers definition and a Dockerfile to initialize the database.
I followed this tutorial, it generally worked without the automated database setup (Dockerfile), but when I try to put the instructions in the Dockerfile, docker throws an error.
docker-compose file:
version: '3'
services:
guacd:
restart: always
image: guacamole/guacd
guacamole-server:
restart: always
image: guacamole/guacamole
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- GUACD_HOSTNAME=guacd
- POSTGRESQL_HOSTNAME=database
- POSTGRESQL_DATABASE=${GUACAMOLE_DATABASE}
- POSTGRESQL_USER=${GUACAMOLE_USER}
- POSTGRESQL_PASSWORD=${GUACAMOLE_PASSWORD}
depends_on:
- guacd
- database
volumes:
- ./initdb.sql:/initdb.sql:ro
database:
restart: always
image: postgres
environment:
- POSTGRES_USER=${GUACAMOLE_USER}
- POSTGRES_DB=${GUACAMOLE_DATABASE}
- POSTGRES_PASSWORD=${GUACAMOLE_PASSWORD}
volumes:
- ./db:/var/lib/postgresql/data:rw
- ./initdb.sql:/initdb.sql:ro
command: >
sh -c "psql -U ${GUACAMOLE_USER} ${GUACAMOLE_DATABASE} -f /initdb.sql &&
tail -f /dev/null"
volumes:
db:
Dockerfile:
# Dockerfile for guacamole/guacamole container
FROM guacamole/guacamole:latest
USER root
# Generate the initdb.sql file for PostgreSQL
RUN /opt/guacamole/bin/initdb.sh --postgresql > initdb.sql
USER guacamole
When i run docker-compose up --build -d
it builds succesfully, only after the build the error below is thrown and the databse (PostgreSQL) container goes into restarting state.
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/scripts/Cherry-VM-Manager/docker/apache-guacamole/initdb.sql" to rootfs at "/initdb.sql": mount /scripts/Cherry-VM-Manager/docker/apache-guacamole/initdb.sql:/initdb.sql (via /proc/self/fd/6), flags: 0x5001: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
Directory with docker-compose file:
total 16
drwxr-xr-x 1 root root 112 Aug 3 18:18 .
drwxr-xr-x 1 root root 74 Jul 25 12:58 ..
-rw-r--r-- 1 root root 82 Aug 3 18:18 .env
-rw-r--r-- 1 root root 217 Aug 3 18:18 Dockerfile
drwxr-xr-x 1 root root 0 Aug 3 17:17 db
-rw-r--r-- 1 root root 1048 Aug 3 18:18 docker-compose.yml
-rw-r--r-- 1 root root 852 Aug 3 18:18 docker-compose.yml.bak
2
Answers
The tutorial includes an initial step to create the
initdb.sql
file. It appears that this step was skipped or was unsuccessful:That step would have created the file in your current directory.
You can’t really share files from one container to another. It looks like in your setup you’re trying to generate the initialization script in one image, then use it in a separate container, and that doesn’t really work.
The Docker Hub
guacamole/guacamole
image page suggests you need to generate theinit.sql
script and execute it outside of Docker. To reiterate its advice, and actually load in the file, I might run (manually, once)(The second line may need to set
$PGUSER
,$PGPASSWORD
, and$PGDATABASE
as well.)If you wanted this to run automatically on container startup, you’d need to arrange for this to happen within the
guacamole-server
container, on startup. I usually use an entrypoint wrapper script for this, which would run the initialization steps and then runexec "$@"
to run the main container command. So that script could look likeYou’d need to find the original Dockerfile (it seems to be this: when your image changes its
ENTRYPOINT
it needs to repeat theCMD
from the original Dockerfile.What’s wrong with the original setup? When the Compose file says
This always takes what’s in
./initdb.sql
on the host system, and replaces what was in the original image with that. So in this setup, theinitdb.sql
file you create in the Dockerfile is lost.I’m guessing the file never existed on the host system, but if you look now,
ls -ld initdb.sql
will show you an empty directory on the host. This is a long-standing Docker behavior to create an empty directory as the source for a bind mount if it doesn’t already exist. When Docker tries to mount that directory over the plain file that’s in the error, that results in the specific error you get.You will also have problems because a container
command:
runs instead of the normal thing the container does. So in this setup you’re trying to runpsql
to load the data, instead of running a database server, and thepsql
command will fail.