RobLoach / drush-docker

:whale: Docker Container to run Drush
http://registry.hub.docker.com/u/drush/drush
Other
19 stars 19 forks source link

How to use docker drush with docker-compose #32

Open JulienD opened 8 years ago

JulienD commented 8 years ago

Hi

This is a more a documentation issue than anything else.

I've downloaded the image and run drush as a standalone container like described on the Readme page and it worked well. In order to go deeper, I want to understand how to link a drush container with others containers but unfortunately I have not been able to make it working.

In my docker-compose.yml file I have defined the following containers:

nginx:
  build: nginx-fpm
  links:
    - phpfpm
  ports:
    - "8080:80"
  volumes_from:
    - data

phpfpm:
  build: php-5.6-fpm-custom
  volumes_from:
    - data
    - db

db:
  image: mariadb
  volumes:
    - /var/run/mysqld
    - ./databases/active:/var/lib/mysql
  environment:
    MYSQL_ROOT_PASSWORD: password
    MYSQL_DATABASE: application

data:
  image: busybox
  stdin_open: true
  volumes:
    - ./htdocs:/var/www/html

drush:
  image: drush/drush
  volumes_from:
    - data
    - db
  links:
    - phpfpm
    - db

When starting all the containers, I can see Drush's container working, displaying the list of commands and them exiting.

....
drush_1   |  (wd-list)            prompt will ask for a choice to show watchdog messages.
drush_1   |  watchdog-show        Show watchdog messages.
drush_1   |  (wd-show, ws)
dockerlemp_drush_1 exited with code 0

I though the container would live as a normal container and would allow me to manage Drupal.

Maybe I did not understand the purpose of this repo or maybe this is due to my short experience with docker and docker-compose but I have not found how to use the repo with several containers. Could you give me a hint on how to achieve it ?

Thanks

theodorosploumis commented 8 years ago

1) You don't need to have a container running, you only need the executable (drush) to be available to the www files where drupal exists. Saying that you can use your local drush executable if you like (if it is a phar file) and avoid drush/drush image at all. Here is an example:

version: '2'
services:
  drupal:
    image: drupal:8.1.1-apache
    container_name: drupal_apache
    volumes:
      # Mount local drush to your container.
      - /usr/local/bin/drush:/drush/drush

then you can run:

# drush status on the created container
docker exec drupal_apache /drush/drush status

2) Normally you could volume the drush executable from drush/drush image but you can't do this since mount is not allowed for files. To do so you can create your own image based on drush/drush. Here is a simple Dockerfile:

FROM drush/drush:8

# Move drush to a more generic path so it can be used with any image
RUN mkdir -p /drush && \
    mv -f /usr/local/bin/drush /drush/drush

# Volume the drush path so we can use it with other containers
VOLUME /drush

# Change the entrypoint to match the new drush path
ENTRYPOINT ["/drush/drush", "status"]

Create the new drush image:

docker build -t drush-volumed:8 .

and here is the docker-compose.yml file using volumes from the new drush-volumed:8 image:

version: '2'
services:
  drupal:
    image: drupal:8.1.1-apache
    container_name: drupal_8081
    volumes:
      - /var/www/html
    volumes_from:
      - drush_volumed
    ports:
      - '8081:80'
    links:
      - mysql
  mysql:
    image: mysql:5.5
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=drupal
      - MYSQL_USER=drupal
      - MYSQL_PASSWORD=drupal
  drush_volumed:
    image: drush-volumed:8
    container_name: drush_volumed

I am about to create a pull request for this as it is major and I think a lot of drupal developers will come to the same issue when they start using docker.

peperoni60 commented 8 years ago

If you do so, you could also install Drush in your drupal container. It shares the PHP and all other stuff. That's not, what is wanted when you use Docker.

opdavies commented 8 years ago

and here is the docker-compose.yml file using volumes from the new drush-volumed:8 image

Where does the drush-volumed:8 image come from?

theodorosploumis commented 8 years ago

It does not exist (not a public image). But here is a simple Dockerfile to create it.

sgarciafer commented 7 years ago

Your last Dockerfile link has gone 404. Could you re-link it?

sgarciafer commented 7 years ago

I'm checking your repo Theodorosploumis, but I see you deleted the separate drush docker container and have drush installed on the same drupal container. Should I guess the option you explain in here didn't work so well after all ?

jubalm commented 7 years ago

I managed to make this work by exposing the the application container's volume to drush/drush and use docker-compose to run drush commands. Here's my docker-compose.yml file.

version: '2'
services:
  app:
    image: drupal:7.53
    container_name: drupal.app
    ports:
      - "8000:80"
    volumes:
      - /var/www/html 
  db:
    image: mariadb
    container_name: drupal.db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: drupal
      MYSQL_DATABASE: drupal
      MYSQL_USER: drupal
      MYSQL_PASSWORD: drupal
  drush:
    image: drush/drush:8
    container_name: drupal.drush
    volumes_from:
      - app

and running the command

$ docker-compose run drush site-install --uri=http://drupal.app --root=/var/www/html

parameters and their corresponding values in docker-compose.yml

This is a awesome presentation about it https://socketwench.github.io/rideTheWhale

james-nesbitt commented 7 years ago

it is actually poor form to install drush in your runtime container. It is also considered poor form to use docker exec

Technically drush needs only 2 things:

  1. access to files (including assets)
  2. access to DB

consider running drush as a new disposable container, linking to your db container, and taking source from local or from your drupal container. You can get source from your drupal container by volumizing the source path and using --sources-from=drupal or --volume drupal:/path/to/source

theodorosploumis commented 7 years ago

@sgarciafer No it works fine. But I am planning to create a complete different repo for Drupal + Docker + "Friends" containers management to cover more cases, OS and versions of software. So I deleted the code from this repo.

On the same repo see https://github.com/theodorosploumis/drupal-docker/blob/master/docker-compose.yml#L41. There are still volumes from MySQL so drush (and drupalconsole) play well.

https://github.com/RobLoach/drush-docker/issues/32#issuecomment-222321265 is still valid as also as an updated answer at http://stackoverflow.com/a/40855933/1365264.

theodorosploumis commented 7 years ago

On a presentation about Docker + Drupal I tried to "separate" the Drupal components and investigate how someone can use them within Docker: https://theodorosploumis.github.io/drupalcamp2016/#/28.

leolandotan commented 7 years ago

@jubalm thanks for that! I'm just wondering, is there a way or configuration that would let run Drush commands without specifying --uri and --root ?

dixhuit commented 7 years ago

@leolandotan Assuming you're not running multisite, many drush commands don't rely on the uri option being set or even accurate. drush user-login needs it to return an accurate path but it's in the minority.

Either way, according to the drush docs you can set the uri option in a drushrc.php file next to your site's settings.php:

$options['uri'] = "http://drupal.app";

Now you only have to worry about setting the root option for each drush command.


OR

You could use drush aliases so long as they're not defined within your site's codebase. A drush alias can define both root and uri options so you'd only need worry about specifying the correct alias in your command and you're golden :)

https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.aliases.drushrc.php

leolandotan commented 7 years ago

@danbohea Thank you very much for these option in details! I'm still starting in Drush and like so I only understand the basics but I will definitely base my additional research and implementation from this! When I'm successful or have any progress I'll try to post them here. :)

leolandotan commented 7 years ago

@danbohea I tried to create a Drush aliases file but the Drush container doesn't seem to detect it.

docker-compose.yml

version: '2'
services:
  web:
    build: docker/php
    volumes:
      - ./www:/var/www/html/mydrupalsite
      - ./www/drush:/etc/drush/site-aliases
    ports:
      - 80
  db:
    image: mysql:5.7
    volumes:
      - ./data/mysql:/var/lib/mysql
    environment:
      MYSQL_USER: default
      MYSQL_PASSWORD: default
      MYSQL_DATABASE: default
      MYSQL_ROOT_PASSWORD: root
  drush:
    image: drush/drush:7
    volumes_from:
      - web
    links:
      - db:mysql

mydrupalsite.aliases.drushrc.php

<?php
$aliases['local'] = array(
  'root' => '/var/www/html/mydrupalsite',
);

Then I ran:

$ docker-compose up -d
Recreating mydrupalsite_web_1
mydrupalsite_db_1 is up-to-date
Recreating mydrupalsite_drush_1
$ docker-compose run --rm drush cc drush
'drush' cache was cleared.
$ docker-compose run --rm drush sa 
@none

I can't figure out what I'm missing.

UPDATE

Instead of using Drush aliases, I used Docker's entrypoint configuration option in the drush service as follows:

  drush:
    image: drush/drush:7
    volumes_from:
      - web
    links:
      - db:mysql
    entrypoint:
      - drush
      - "--root=/var/www/html/mydrupalsite"

So when I issue the docker-compose run --rm drush st command, it runs the first item as the command and the successive items as its parameters including my st command.

I hope this is an acceptable solution. What do you think guys?

Entrypoint Reference: https://docs.docker.com/engine/reference/builder/#entrypoint

elalemanyo commented 7 years ago

@leolandotan I am using your way to use drush... but how do you run drush make project.make? I try like this: docker-compose run --rm drush, but I get this error: file_get_contents(project.make): failed to open stream: No such file

Thanks!

RobLoach commented 7 years ago

@elalemanyo The other option is to get into Bash through run....

docker-compose run drush bash

After that, feel free to run any command you wish.

elalemanyo commented 7 years ago

@RobLoach: Drush make still not working using docker-compose run drush bash

this is the docker-compose that I am trying to use:

version: '2'

services:
  web:
    container_name: ${PROJECT_NAME}-web
    restart: always
    image: nginx:latest
    links:
      - phpfpm:phpfpm
      - mysql:mysql
    volumes:
      - ./nginx/vhost.conf:/etc/nginx/conf.d/default.conf
      - ./log/nginx:/var/log/nginx
      - ../../../:/var/www/html

  phpfpm:
    container_name: ${PROJECT_NAME}-phpfpm
    restart: always
    image: php:5.6.30-fpm
    build: ./php-fpm-5.6
    volumes:
      - ./php-fpm-5.6/php-fpm.conf:/usr/local/etc/php-fpm.conf
      - ./php-fpm-5.6/php.ini:/usr/local/etc/php/php.ini
      - ./log/php-fpm:/var/log/php-fpm
      - ../../../:/var/www/html

  mysql:
    container_name: ${PROJECT_NAME}-mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASS: ${MYSQL_PASS}
    volumes:
      - ./mysql/data/:/var/lib/mysql
    ports:
      - "3306:3306"

  drush:
    container_name: ${PROJECT_NAME}-drush
    image: drush/drush:7
    volumes_from:
      - web
    links:
      - mysql:mysql
    entrypoint:
      - drush
      - "--root=/var/www/html/drupal"

networks:
  default:
    external:
      name: haproxy_default
leolandotan commented 7 years ago

Hi @elalemanyo I'm not very good yet at Docker but I'll try to help. If I saw it right, in your web service you have:

volumes:
  - ...
  - ../../../:/var/www/html

which I think means your Drupal root is inside the /html directory.

Then on your drush service, your root is set to look into --root=/var/www/html/drupal which I think should match /var/www/html where your Drupal site is located.

Could you please try updating the drush service's --root value please.

Thanks!

elalemanyo commented 7 years ago

Hi @leolandotan, The new service's --root value do not fix the problem. If I use the one you suggested all drush commands stop working. With the old one all the commands I usually use work perfectly (cc fl fd...), just make command still not working.

Thanks!

leolandotan commented 7 years ago

Hi @elalemanyo,

I did additional research on this and got it to work. I noticed that in Drush's Docker page, some examples to use the service is by running docker run -v $(pwd):/app drush/drush where it mounts the Drupal site root inside the container.

Correct me if I'm wrong but this may be related to the directory permissions of the Drush image because in their example, they mount the host drupal directory to the container’s /app folder. When I used the example Docker command with the Drush make command, it worked. So I adjusted the Drush service configuration in my docker-compose.yml file to simply:

drush:
  image: drush/drush:8
  volumes:
    # We directly mount the Drupal directory from the host into container's
    #  /app directory like as RobLoach instructed.
    - ./www:/app

NOTE: With this approach we don't need to use --root or any other explicit directory assignment since the Drush container already is working in its normal directory which is /app.

Now with this make file:

core: 7.x
api: 2
projects:
  drupal:
    version: '7.56'
  views:
    version: ~
  ctools:
    version: ~

Running docker-compose run --rm drush make test.make generated the following output:

➜  drupal7Docker docker-compose run --rm drush make test.make
Make new site in the current directory? (y/n): y
Beginning to build test.make.                                                                                                                                                                    [ok]
drupal-7.56 downloaded.                                                                                                                                                                          [ok]
Project views contains 2 modules: views, views_ui.
views-7.x-3.16 downloaded.                                                                                                                                                                       [ok]
Project ctools contains 10 modules: bulk_export, ctools_plugin_example, page_manager, views_content, stylizer, ctools_access_ruleset, ctools_custom_content, term_depth, ctools_ajax_sample, ctools.
ctools-7.x-1.12 downloaded.                                                                                                                                                                          [ok]
➜  drupal7Docker

Hope everything is in order.

Thanks!

elalemanyo commented 7 years ago

Hi @leolandotan, Sorry I was busy with other stuff and I could not test your suggestion. I fix the issue moving the make file to the main project directory, before make file was inside Drupal directory. Now make command is working again.

Thanks for your help!

GuyPaddock commented 5 years ago

In our case, we have a multi-stage build that assembles a container image around a Drupal installation assembled using drush make. In addition, our profile is based on Pressflow, so that gives us the ability to initialize Drupal just by populating PRESSFLOW_SETTINGS, just like Pantheon does. So, whenever we need to run a copy of Drupal with our profile, we can just specify the database connection settings via run-time environment variables, launch the image, and be up and running in seconds.

Unfortunately, both of these characteristics complicated running Drush in a separate container because it needs to be running off the same Drupal codebase that the Drupal container is running off of AND it has to initialize the database the same way (from the environment).

To satisfy these constraints, we did the following:

Here's a slimmed-down version of the docker-compose.yml file for the above, which worked for us:

version: '3.2'

services:
  mysql:
    image: mysql:5.5
    command: --max_allowed_packet=256M
    restart: always
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "true"
      MYSQL_DATABASE: "drupal"
      MYSQL_USER: "drupal"
      MYSQL_PASSWORD: "changeit"
    volumes:
      - mysql_databases:/var/lib/mysql

  drupal:
    image: inveniem/drupal-apache:latest
    restart: "always"
    ports:
      - 8080:80
    depends_on:
      - mysql
    volumes:
      # This takes advantage of the feature in Docker that a new volume will
      # be initialized with the existing content of the image at the same
      # location.
      #
      # This allows the code for core + contrib to be shared with Drush.
      - drupal_core:/var/www/html
      - drupal_sites:/var/www/html/sites

      # Mount host copies of profile code, to streamline development
      - type: bind
        source: &drupal_custom_modules ../INSTALL_PROFILE/modules/custom
        target: /var/www/html/profiles/INSTALL_PROFILE/modules/custom
      - type: bind
        source: &drupal_feature_modules ../INSTALL_PROFILE/modules/features
        target: /var/www/html/profiles/INSTALL_PROFILE/modules/features
    environment:
      PRESSFLOW_SETTINGS: &pressflow_settings |
        {
          "conf": {
            "pressflow_smart_start": true,
            "redis_client_host": null,
            "redis_client_port": null,
            "redis_client_password": null,
            "file_public_path": "sites/default/files",
            "file_private_path": "sites/default/files/private",
            "file_directory_path": "sites/default/files",
            "file_temporary_path": "/tmp",
            "file_directory_temp": "/tmp",
            "css_gzip_compression": true,
            "js_gzip_compression": true,
            "page_compression": true
          },
          "databases": {
            "default": {
              "default": {
                "host": "mysql",
                "port": 3306,
                "database": "drupal",
                "username": "drupal",
                "password": "changeit",
                "driver": "mysql"
              }
            }
          },
          "drupal_hash_salt": "714468be2f46d1ddbaed65c82817b3fe337cda9e4f37234c906e5b1015648bd0",
          "config_directory_name": "config"
        }

  drush:
    image: drush/drush:8
    restart: "no"
    depends_on:
      - drupal
      - mysql
    volumes:
      - drupal_core:/app
      - drupal_sites:/app/sites
      - type: bind
        source: *drupal_custom_modules
        target: /app/profiles/INSTALL_PROFILE/modules/custom
      - type: bind
        source: *drupal_feature_modules
        target: /app/profiles/INSTALL_PROFILE/modules/features
    environment:
      PRESSFLOW_SETTINGS: *pressflow_settings

volumes:
  mysql_databases:
  drupal_core:
  drupal_sites:

Where INSTALL_PROFILE is the name of our installation profile.

EnzoJURET commented 4 years ago

Hi, I'm new to the amazing world of docker deployment, I stumbled upon this issue, because after I set up my docker-compose-.yml file, I tried to use the drush commands ... However, despite having read all the comments, I did not find a solution for my case:

docker-compose config

version: "3"

services:

#########################################
  mariadb:
    image: wodby/mariadb:$MARIADB_TAG
    container_name: "${PROJECT_NAME}_mariadb"
    stop_grace_period: 30s
    environment:
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
 #   volumes:
 #     - ./mariadb-init:/docker-entrypoint-initdb.d # Placer votre fichier d'initialsation .sql à cette adresse.

########################################
  php:
    image: wodby/drupal-php:$PHP_TAG
    container_name: "${PROJECT_NAME}_php"
    environment:
      DB_HOST: $DB_HOST
      DB_PORT: $DB_PORT
      DB_USER: $DB_USER
      DB_PASSWORD: $DB_PASSWORD
      DB_NAME: $DB_NAME
      DB_DRIVER: $DB_DRIVER
      PHP_FPM_USER: wodby
      PHP_FPM_GROUP: wodby
      COLUMNS: 80
    volumes:
      - ../drupal_tic/:/var/www/html

#########################################
  nginx:
    image: wodby/nginx:$NGINX_TAG
    container_name: "${PROJECT_NAME}_nginx"
    depends_on:
      - php
    environment:
      NGINX_STATIC_OPEN_FILE_CACHE: "off"Debug)
      NGINX_ERROR_LOG_LEVEL: debug
      NGINX_BACKEND_HOST: php
      NGINX_SERVER_ROOT: /var/www/html/web
      NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET
    volumes:
      - ../drupal_tic/:/var/www/html
    labels:
      - "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_BASE_URL}`)"

##########################################
  traefik:
    image: traefik:v2.0
    container_name: "${PROJECT_NAME}_traefik"
    command: --api.insecure=true --providers.docker
    ports:
      - '9025:80'Docker, afin que Traefik connaissent l'emplacement sur lequel il doit agir
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Do I have to create a specific drush container to link it to my drupal and database, or do I have to create aliases?

In my case I use the docker-compose of this project : docker4drupal

So I don't use basic images, but images modified by wodby, moreover I don't use drupal container, how do I connect my drush container with drupal ?

leolandotan commented 4 years ago

@Enzo-JURET Have you tried the approach that I did? https://github.com/RobLoach/drush-docker/issues/32#issuecomment-320514925. What happens is that the Drush container just has the right amount of packages to execute Drupal commands and just communicate with the database container. So if you have issues, also try to check if the Drush container can communicate/see your database container.