| |
| Docker Solr FAQ |
| =============== |
| |
| |
| How do I persist Solr data and config? |
| -------------------------------------- |
| |
| Your data is persisted already, in your container's filesystem. |
| If you `docker run`, add data to Solr, then `docker stop` and later |
| `docker start`, then your data is still there. The same is true for |
| changes to configuration files. |
| |
| Equally, if you `docker commit` your container, you can later create a new |
| container from that image, and that will have your data in it. |
| |
| For some use-cases it is convenient to provide a modified `solr.in.sh` file to Solr. |
| For example to point Solr to a ZooKeeper host: |
| |
| ``` |
| docker create --name my_solr -P solr |
| docker cp my_solr:/opt/solr/bin/solr.in.sh . |
| sed -i -e 's/#ZK_HOST=.*/ZK_HOST=cylon.lan:2181/' solr.in.sh |
| docker cp solr.in.sh my_solr:/opt/solr/bin/solr.in.sh |
| docker start my_solr |
| # With a browser go to http://cylon.lan:32873/solr/#/ and confirm "-DzkHost=cylon.lan:2181" in the JVM Args section. |
| ``` |
| |
| But usually when people ask this question, what they are after is a way |
| to store Solr data and config in a separate [Docker Volume](https://docs.docker.com/userguide/dockervolumes/). |
| That is explained in the next two questions. |
| |
| |
| How can I mount a host directory as a data volume? |
| -------------------------------------------------- |
| |
| This is useful if you want to inspect or modify the data in the Docker host |
| when the container is not running, and later easily run new containers against that data. |
| This is indeed possible, but there are a few gotchas. |
| |
| Solr stores its core data in the `server/solr` directory, in sub-directories |
| for each core. The `server/solr` directory also contains configuration files |
| that are part of the Solr distribution. |
| Now, if we mounted volumes for each core individually, then that would |
| interfere with Solr trying to create those directories. If instead we make |
| the whole directory a volume, then we need to provide those configuration files |
| in our volume, which we can do by copying them from a temporary container. |
| For example: |
| |
| ``` |
| # create a directory to store the server/solr directory |
| $ mkdir /home/docker-volumes/mysolr1 |
| |
| # make sure its host owner matches the container's solr user |
| $ sudo chown 8983:8983 /home/docker-volumes/mysolr1 |
| |
| # copy the solr directory from a temporary container to the volume |
| $ docker run -it --rm -v /home/docker-volumes/mysolr1:/target apache/solr cp -r server/solr /target/ |
| |
| # pass the solr directory to a new container running solr |
| $ SOLR_CONTAINER=$(docker run -d -P -v /home/docker-volumes/mysolr1/solr:/opt/solr/server/solr apache/solr) |
| |
| # create a new core |
| $ docker exec -it --user=solr $SOLR_CONTAINER solr create_core -c gettingstarted |
| |
| # check the volume on the host: |
| $ ls /home/docker-volumes/mysolr1/solr/ |
| configsets gettingstarted README.txt solr.xml zoo.cfg |
| ``` |
| |
| Note that if you add or modify files in that directory from the host, you must `chown 8983:8983` them. |
| |
| |
| How can I use a Data Volume Container? |
| -------------------------------------- |
| |
| You can avoid the concerns about UID mismatches above, by using data volumes only from containers. |
| You can create a container with a volume, then point future containers at that same volume. |
| This can be handy if you want to modify the solr image, for example if you want to add a program. |
| By separating the data and the code, you can change the code and re-use the data. |
| |
| But there are pitfalls: |
| |
| - if you remove the container that owns the volume, then you lose your data. |
| Docker does not even warn you that a running container is dependent on it. |
| - if you point multiple solr containers at the same volume, you will have multiple instances |
| write to the same files, which will undoubtedly lead to corruption |
| - if you do want to remove that volume, you must do `docker rm -v containername`; |
| if you forget the `-v` there will be a dangling volume which you can not easily clean up. |
| |
| Here is an example: |
| |
| ``` |
| # create a container with a volume on the path that solr uses to store data. |
| docker create -v /opt/solr/server/solr --name mysolr1data solr /bin/true |
| |
| # pass the volume to a new container running solr |
| SOLR_CONTAINER=$(docker run -d -P --volumes-from=mysolr1data apache/solr) |
| |
| # create a new core |
| $ docker exec -it --user=solr $SOLR_CONTAINER solr create_core -c gettingstarted |
| |
| # make a change to the config, using the config API |
| docker exec -it --user=solr $SOLR_CONTAINER curl http://localhost:8983/solr/gettingstarted/config -H 'Content-type:application/json' -d'{ |
| "set-property" : {"query.filterCache.autowarmCount":1000}, |
| "unset-property" :"query.filterCache.size"}' |
| |
| # verify the change took effect |
| docker exec -it --user=solr $SOLR_CONTAINER curl http://localhost:8983/solr/gettingstarted/config/overlay?omitHeader=true |
| |
| # stop the solr container |
| docker exec -it --user=solr $SOLR_CONTAINER bash -c 'cd server; java -DSTOP.PORT=7983 -DSTOP.KEY=solrrocks -jar start.jar --stop' |
| |
| # create a new container |
| SOLR_CONTAINER=$(docker run -d -P --volumes-from=mysolr1data apache/solr) |
| |
| # check our core is still there: |
| docker exec -it --user=solr $SOLR_CONTAINER ls server/solr/gettingstarted |
| |
| # check the config modification is still there: |
| docker exec -it --user=solr $SOLR_CONTAINER curl http://localhost:8983/solr/gettingstarted/config/overlay?omitHeader=true |
| ``` |
| |
| |
| Can I use volumes with SOLR_HOME? |
| --------------------------------- |
| |
| Solr supports a SOLR_HOME environment variable to point to a non-standard location of the Solr home directory. |
| You can use this in Solr docker, in combination with volumes: |
| |
| ``` |
| docker run -it -v $PWD/mysolrhome:/mysolrhome -e SOLR_HOME=/mysolrhome apache/solr |
| ``` |
| |
| This does need a pre-configured directory at that location. |
| |
| To make this easier, Solr docker supports a INIT_SOLR_HOME setting, which copies the contents |
| from the default directory in the image to the SOLR_HOME (if it is empty). |
| |
| ``` |
| mkdir mysolrhome |
| sudo chown 8983:8983 mysolrhome |
| docker run -it -v $PWD/mysolrhome:/mysolrhome -e SOLR_HOME=/mysolrhome -e INIT_SOLR_HOME=yes apache/solr |
| ``` |
| |
| Note: If SOLR_HOME is set, the "solr-precreate" command will put the created core in the SOLR_HOME directory |
| rather than the "mycores" directory. |
| |
| |
| Can I run ZooKeeper and Solr clusters under Docker? |
| --------------------------------------------------- |
| |
| At the network level the ZooKeeper nodes need to be able to talk to eachother, |
| and the Solr nodes need to be able to talk to the ZooKeeper nodes and to each other. |
| At the application level, different nodes need to be able to identify and locate each other. |
| In ZooKeeper that is done with a configuration file that lists hostnames or IP addresses for each node. |
| In Solr that is done with a parameter that specifies a host or IP address, which is then stored in ZooKeeper. |
| |
| In typical clusters, those hostnames/IP addresses are pre-defined and remain static through the lifetime of the cluster. |
| In Docker, inter-container communication and multi-host networking can be facilitated by [Docker Networks](https://docs.docker.com/engine/userguide/networking/). |
| But, crucially, Docker does not normally guarantee that IP addresses of containers remain static during the lifetime of a container. |
| In non-networked Docker, the IP address seems to change everytime you stop/start. |
| In a networked Docker, containers can lose their IP address in certain sequences of starting/stopping, unless you take steps to prevent that. |
| |
| IP changes causes problems: |
| |
| - If you use hardcoded IP addresses in configuration, and the addresses of your containers change after a stops/start, then your cluster will stop working and may corrupt itself. |
| - If you use hostnames in configuration, and the addresses of your containers change, then you might run into problems with cached hostname lookups. |
| - And if you use hostnames there is another problem: the names are not defined until the respective container is running, |
| So when for example the first ZooKeeper node starts up, it will attempt a hostname lookup for the other nodes, and that will fail. |
| This is especially a problem for ZooKeeper 3.4.6; future versions are better at recovering. |
| |
| Docker 1.10 has a new `--ip` configuration option that allows you to specify an IP address for a container. |
| It also has a `--ip-range` option that allows you to specify the range that other containers get addresses from. |
| Used together, you can implement static addresses. See [this example](docs/docker-networking.md). |
| |
| |
| Can I run ZooKeeper and Solr with Docker Links? |
| ----------------------------------------------- |
| |
| Docker's [Legacy container links](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/) provide a way to |
| pass connection configuration between containers. It only works on a single machine, on the default bridge. |
| It provides no facilities for static IPs. |
| Note: this feature is expected to be deprecated and removed in a future release. |
| So really, see the "Can I run ZooKeeper and Solr clusters under Docker?" option above instead. |
| |
| But for some use-cases, such as quick demos or one-shot automated testing, it can be convenient. |
| |
| Run ZooKeeper, and define a name so we can link to it: |
| |
| ```console |
| $ docker run --name zookeeper -d -p 2181:2181 -p 2888:2888 -p 3888:3888 jplock/zookeeper |
| ``` |
| |
| Run two Solr nodes, linked to the zookeeper container: |
| |
| ```console |
| $ docker run --name solr1 --link zookeeper:ZK -d -p 8983:8983 \ |
| apache/solr \ |
| bash -c 'solr start -f -z $ZK_PORT_2181_TCP_ADDR:$ZK_PORT_2181_TCP_PORT' |
| |
| $ docker run --name solr2 --link zookeeper:ZK -d -p 8984:8983 \ |
| apache/solr \ |
| bash -c 'solr start -f -z $ZK_PORT_2181_TCP_ADDR:$ZK_PORT_2181_TCP_PORT' |
| ``` |
| |
| Create a collection: |
| |
| ```console |
| $ docker exec -i -t solr1 solr create_collection \ |
| -c gettingstarted -shards 2 -p 8983 |
| ``` |
| |
| Then go to `http://localhost:8983/solr/#/~cloud` (adjust the hostname for your docker host) to see the two shards and Solr nodes. |
| |
| |
| How can I run ZooKeeper and Solr with Docker Compose? |
| ----------------------------------------------------- |
| |
| See the [docker compose example](docs/docker-compose.yml). |
| |
| |
| I'm confused about the different invocations of solr -- help? |
| ------------------------------------------------------------- |
| |
| The different invocations of the Solr docker image can look confusing, because the name of the |
| image is "apache/solr" and the Solr command is also "solr", and the image interprets various arguments in |
| special ways. I'll illustrate the various invocations: |
| |
| |
| To run an arbitrary command in the image: |
| |
| ``` |
| docker run -it apache/solr date |
| ``` |
| |
| here "apache/solr" is the name of the image, and "date" is the command. |
| This does not invoke any solr functionality. |
| |
| |
| To run the Solr server: |
| |
| ``` |
| docker run -it apache/solr |
| ``` |
| |
| Here "apache/solr" is the name of the image, and there is no specific command, |
| so the image defaults to run the "solr" command with "-f" to run it in the foreground. |
| |
| |
| To run the Solr server with extra arguments: |
| |
| ``` |
| docker run -it apache/solr -h myhostname |
| ``` |
| |
| This is the same as the previous one, but an additional argument is passed. |
| The image will run the "solr" command with "-f -h myhostname" |
| |
| To run solr as an arbitrary command: |
| |
| ``` |
| docker run -it apache/solr solr zk --help |
| ``` |
| |
| here the first "apache/solr" is the image name, and the second "solr" |
| is the "solr" command. The image runs the command exactly as specified; |
| no "-f" is implicitly added. The container will print help text, and exit. |
| |
| If you find this visually confusing, it might be helpful to use more specific image tags, |
| and specific command paths. For example: |
| |
| ``` |
| docker run -it apache/solr:6 bin/solr -f -h myhostname |
| ``` |
| |
| Finally, the Solr docker image offers several commands that do some work before |
| then invoking the Solr server, like "solr-precreate" and "solr-demo". |
| See the README.md for usage. |
| These are implemented by the `docker-entrypoint.sh` script, and must be passed |
| as the first argument to the image. For example: |
| |
| ``` |
| docker run -it apache/solr:6 solr-demo |
| ``` |
| |
| It's important to understand an implementation detail here. The Dockerfile uses |
| `solr-foreground` as the `CMD`, and the `docker-entrypoint.sh` implements |
| that by by running "solr -f". So these two are equivalent: |
| |
| ``` |
| docker run -it apache/solr:6 |
| docker run -it apache/solr:6 solr-foreground |
| ``` |
| |
| whereas: |
| |
| ``` |
| docker run -it apache/solr:6 solr -f |
| ``` |
| |
| is slightly different: the "solr" there is a generic command, not treated in any |
| special way by `docker-entrypoint.sh`. In particular, this means that the |
| `docker-entrypoint-initdb.d` mechanism is not applied. |
| So, if you want to use `docker-entrypoint-initdb.d`, then you must use one |
| of the other two invocations. |
| You also need to keep that in mind when you want to invoke solr from the bash |
| command. For example, this does NOT run `docker-entrypoint-initdb.d` scripts: |
| |
| ``` |
| docker run -it -v $PWD/set-heap.sh:/docker-entrypoint-initdb.d/set-heap.sh \ |
| apache/solr:6 bash -c "echo hello; solr -f" |
| ``` |
| |
| but this does: |
| |
| ``` |
| docker run -it $PWD/set-heap.sh:/docker-entrypoint-initdb.d/set-heap.sh \ |
| apache/solr:6 bash -c "echo hello; /opt/docker-solr/scripts/docker-entrypoint.sh solr-foreground" |
| ``` |