0

I'm trying to replicate docker run command with options within a docker-compose file:

My Dockerfile is:

FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -y 
RUN apt-get install -y python3-pip python3-dev python3-opencv
RUN apt-get install -y libcanberra-gtk-module libcanberra-gtk0 libcanberra-gtk3-module

WORKDIR /

RUN mkdir /imgs

COPY app.py ./

CMD ["/bin/bash"]

And I use the following command to run the container so that it can display images from shared volume properly:

docker build -t docker_test:v1 .
docker run -it --net=host --env=DISPLAY --volume=$HOME/.Xauthority:/root/.Xauthority docker_test:v1

In order to replicate the previous command, I tried the docker-compose file below:

version: "3.7"

services:   docker_test:
    container_name: docker_test
    build: .
    environment:
      - DISPLAY=:1
    volumes:
      - $HOME/.Xauthority:/root/.Xauthority
      - $HOME/docker_test/imgs:/imgs
    network_mode: "host"

However, after building the image and running app script from inside container (image copied on container, not from shared volume):

docker-compose up
docker run -ti docker_test_docker_test
python3 app.py

The following error arises:

Unable to init server: Could not connect: Connection refused

(OpenCV Image Reading:9): Gtk-WARNING **: 09:15:24.889: cannot open display: 

In addition, volumes do not seem to be shared

rluq
  • 37
  • 1
  • 8

1 Answers1

1

docker run never looks at a docker-compose.yml file; every option you need to run the container needs to be specified directly in the docker run command. Conversely, Compose is much better at running long-running process than at running interactive shells (and you want the container to run the program directly, in the much the same way you don't typically start a python REPL and invoke main() from there).

With your setup, first you're launching a container via Compose. This will promptly exit (because the main container command is an interactive bash shell and it has no stdin). Then, you're launching a second container with default options and manually running your script there. Since there's no docker run -e DISPLAY option, it doesn't see that environment variable.

The first thing to change here, then, is to make the image's CMD be to start the application

...
COPY app.py .
CMD ./app.py

Then running docker-compose up (or docker run your-image) will start the application without further intervention from you. You probably need a couple of other settings to successfully connect to the host display (propagating $DISPLAY unmodified, mounting the host's X socket into the container); see Can you run GUI applications in a Linux Docker container?.

(If you're trying to access the host display and use the host network, consider whether an isolation system like Docker is actually the right tool; it would be much simpler to directly run ./app.py in a Python virtual environment.)

David Maze
  • 130,717
  • 29
  • 175
  • 215