12

I want to use docker-compose to compose together php and several databases (orientdb, neo4j, etc). Then get into the php container and use the shell to execute commands.

Individually, all of my container work swimmingly, and when I compose them together, they all run. However, I cannot for the life of me figure out how to keep the php container alive so I can get into it for testing.

For simplicity, I'll just use a single database: orient-db.

My docker-compose.yml file:

version: '2'
services:
  php:
    build: .
    links:
       - orientdb

  orientdb:
    image: orientdb:latest
    environment:
      ORIENTDB_ROOT_PASSWORD: rootpwd
    ports:
       - "2424:2424"
       - "2480:2480"

My "php" Dockerfile:

FROM php:5.6-cli
ADD . /spider
WORKDIR /spider
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer
RUN composer install --prefer-source --no-interaction

RUN yes | pecl install xdebug \
    && echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini

I have tried (among other things):

  • docker-compose up in one terminal and then docker attach in another
  • enabling tty and stdin_open in my compose file
  • using a /bin/bash command
  • variations of CMD exec vendor/bin/phpunit -D FOREGROUND

And some references I've tried: - How to Keep Docker Container Running After Starting Services? - https://github.com/docker/compose/issues/1926 - https://github.com/docker/compose/issues/423

Any help would really be appreciated.

Thank you.

Community
  • 1
  • 1
Apollo
  • 945
  • 2
  • 9
  • 24
  • Please add pastes of logs of the PHP container. We need to see how it dies. – L0j1k May 10 '16 at 21:13
  • @L0j1k When I run `docker logs all I get is `Interactive Shell`. The container is being built correctly, just exiting as soon as its finished. I need a command to run that will keep it open. I tried @tfg answer but no go so far – Apollo May 11 '16 at 15:13
  • 1
    please look here - just found a simple and working recipe: http://stackoverflow.com/a/38292749/1329943 – Serge Velikan Jul 10 '16 at 14:08
  • Also, you can try using `php:5.6-apache` image instead, as that has the Apache process running by default and won't exit. – Jānis Elmeris Jul 28 '17 at 12:15

4 Answers4

11

So docker-compose is just a stand-in for the docker-engine client. It maintains feature parity with the client. For diagnosing problems like this, you should drop the use of docker-compose until you get it working with the regular ole client. Based on your comments here and on the other answer, it just sounds like you're not running a container with a daemon process in the foreground. If you want to run an interactive shell in Docker, you have to use the -it flags (-t allocates a tty and -i initiates an interactive session). If you don't run Docker with those switches, your container won't survive you starting an interactive shell, e.g. php -a.

It helps to think of Docker as a fancy way to run a process and not a virtual machine. It's not some "environment" that exists outside of the lifetime of whatever process (and its children) you are running. Normally, PHP is invoked by some server (e.g. Apache, Nginx, etc). What you're implying here is that you need a PHP process to run "permanently" so that you can drop into the container and test some things. Except for the interactive shell, that's not going to be possible, and you need specifically to use the -it switch to keep an interactive shell process alive in your container. The real answer here is that you can't do what you're trying to do here (keep a PHP container running) without some related daemon/server process listening in the foreground. The reason for that is because that's not how PHP works. If you really want to get into a container from your PHP image, just drop into a shell on it:

docker run -it apollo/php /bin/bash

... And you'll start a container from your PHP image, and get a shell on the container (which will die as soon as you exit the shell). But again, just reiterating from my first paragraph, docker-compose is not the way to go here.

L0j1k
  • 12,255
  • 7
  • 53
  • 65
  • That makes a lot of sense, and that is what I was fearing. I CAN get php to stay open using the flags. I was just hoping I could use compose in order to link my containers together. The php container needs to be able to communicate with the orientdb container. That's probably a separate question – Apollo May 11 '16 at 15:53
  • Have you considered FROM'ing your OrientDB container and installing PHP inside of it? This is what I would do. – L0j1k May 11 '16 at 16:14
  • 2
    That is a great idea. If there are several databases, I would just need to do this once -- inside a container that stays alive. The others can be linked to it. – Apollo May 11 '16 at 16:34
  • In any case, you've answered my question. Thank you. – Apollo May 11 '16 at 16:34
  • It is also possible (though not recommended) to use several different processes inside one container using supervisord. I've [written a post](https://curtisz.com/running-crons-in-docker-with-supervisord/) with an example using cron, but it is perfectly equivalent to using other processes. The reason this is not recommended is specifically because of the "microservices" design pattern which Docker points to, however, it is totally possible and there's tons of prior work out there demonstrating it. With respect to the microservices architecture, putting PHP inside of another container is normal. – L0j1k May 11 '16 at 16:48
8

Had a similar issue with running a zsh shell on docker container running with compose, it would close with exit code 0 immediately after start.

@Spock's comment below the last answer is actually the key, at least for what I need.

Set your docker-compose command for the image to be:

command: tail -f /dev/null

This keeps the process alive but also allows it to shutdown gracefully.

SeedyROM
  • 2,203
  • 1
  • 18
  • 22
  • 1
    Completely useless when you are already using the command for something else. Docker does not allow you to run multiple commands. – mae May 27 '21 at 06:04
  • Write an entrypoint script if you aren't managing a single process! Don't shoot the messenger. – SeedyROM May 27 '21 at 06:05
5

If you run with docker-compose up and there are no errors printed to the terminal then it suggests that the service is stopping because it is finished (as opposed to encountering some error).

One potential cause for error is that you are sending stuff to PHP (installing composer) which will kill the interactive php terminal that is fired by the php:5.6-cli image. To start the interactive php shell again add the following to the end of your Dockerfile:

CMD ["php", "-a"]

and try again with docker-compose up

Sidenote: when everything is running properly you can run docker-compose up -d to run in daemon mode, giving you control of your terminal again (all stdout + stderr will be logged within the docker container's respective log files).

You can then attach to the container to do your thing. I always found that docker exec -it <containerID> bash was quicker than docker attach <container id>

Hope this helps.

tgallacher
  • 1,594
  • 1
  • 10
  • 7
  • Well, I tried that with some variations, but no go. You are right. When I run `docker ps -a` it shows the php as exited. – Apollo May 11 '16 at 15:10
  • And I just tried adding `command: ["sleep", "60"]` to my yml file, and it kept the container open for the full minute, during which time I could `exec` in – Apollo May 11 '16 at 15:30
  • 3
    command: "tail -f /dev/null" will keep a container running for all time – Spock Jul 19 '16 at 20:05
5

Join entrypoint so that the process does not exit

version: "3.7"
services:
    debug-srv:
        container_name: "debug-srv"
        image: "alpine:latest"
        entrypoint: ["tail", "-f", "/dev/null"]
        networks:
            debug-net:
networks:
    debug-net:
        name: "debug-net"
lupguo
  • 1,525
  • 13
  • 13