Docker
  • 12 Feb 2022
  • 10 Minutes to read
  • Dark
    Light

Docker

  • Dark
    Light

Overview

Docker is a set of platform-as-a service products that use OS-level virtualization to deliver software in packages called containers. This product allows you to run and configure Graylog in concert with its dependencies, MongoDB, and Elasticsearch.

Requirements

You will need a recent version of Docker. In addition, use the following Docker images in this chapter:

If you prefer to run the containers together you could configure all the containers above in a yaml file. To do this, install Docker Compose. Refer to Settings for Compose examples.

Warning

All configuration examples are created to run on the local computer. Should those be used on external servers, adjust GRAYLOG_HTTP_EXTERNAL_URIand add GRAYLOG_HTTP_PUBLISH_URIand GRAYLOG_HTTP_EXTERNAL_URIaccording to the server.conf documentation.

How to get log data in

You can create different kinds of inputs under System / Inputs. However, you can only use ports that have been properly mapped to your Docker container, otherwise data will not show up in the Graylog UI.

docker run --link mongo --link elasticsearch \    
    -p 9000:9000 -p 12201:12201 -p 1514:1514 -p 5555:5555 \    
    -e GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9000/" \    
    -d graylog/graylog:<version_number>

For example, to start a Graylog Docker container listening on port 5555, stop your container and recreate it, while appending -p 5555:5555to your docker run command:

Similarly, the same can be done for UDP by appending -p 5555:5555/udp.

After ensuring that your Graylog Docker container is listening on :5555, create a Raw/Plaintext Input by navigating to your Graylog port, e.g. http://localhost:9000/system/inputs

docker-01.png

docker-02.png
Once on the Inputs page, search for Raw/Plaintext TCPand click Launch new input

docker-03.png

docker-04.png

After launching the input, you’ll see a dialog box pop up with several options. You can leave most these options as their defaults, but note that you’ll need to provide a name for the input, as well as select the node, or “Global” for the location for the input.

docker-05.png
After that you can send a plaintext message to the Graylog Raw/Plaintext TCP input running on port 5555 using the following command:

$ echo 'First log message' | nc localhost 5555

Which you can then view in the Graylog UI:
docker-06.png

Settings

Graylog comes with a default configuration that works out of the box, but you have to set a password for the admin user and the web interface needs to know how to connect from your browser to the Graylog REST API.

Both settings can be configured via environment variables (also see Configuration):

-e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
-e GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9000/"

In this case you can login to Graylog with the username and password admin.

Generate your own admin password with the following command and put the SHA-256 hash into the GRAYLOG_ROOT_PASSWORD_SHA2environment variable:

echo -n "Enter Password: " && head -1 < /dev/stdin | tr -d '\n' | sha256sum | cut -d " " -f1

All these settings and command line parameters can be put in a docker-compose.yml
file, so that they don’t have to be executed one after the other.

Warning

The following example does not persist any data and configurations. You should read the section Persisting data to add persistance to your docker-compose file.

Example Version 2:

version: '2'
services:
  # MongoDB: https://hub.docker.com/_/mongo/
  mongodb:
    image: mongo:3
  #DB in share for persistence
    volumes:
       - /video/graylog/mongodb:/data/db
  # Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/6.6/docker.html
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
    #data folder in share for persistence
    volumes:
      - /video/graylog/elasticsearchdata:/usr/share/elasticsearch/data
    environment:
      - http.host=0.0.0.0
      - transport.host=localhost
      - network.host=0.0.0.0
      - node.max_local_storage_nodes=4
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 1g
  # Graylog: https://hub.docker.com/r/graylog/graylog/
  graylog:
    image: graylog/graylog:<version>
    #journal and config directories in local NFS share for persistence
    volumes:
       - /video/graylog/journal:/usr/share/graylog/data/journal
       - /video/graylog/config:/usr/share/graylog/data/config
    environment:
      # CHANGE ME (must be at least 16 characters)!
      - GRAYLOG_PASSWORD_SECRET=forpasswordencryption
      # Password: admin
      - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
      - GRAYLOG_HTTP_BIND_ADDRESS=0.0.0.0:7555
      - GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.10.152:7555/
      - GRAYLOG_TRANSPORT_EMAIL_WEB_INTERFACE_URL=http://192.168.10.152:7555
      - GRAYLOG_TRANSPORT_EMAIL_HOSTNAME=smtp.example.com
      - GRAYLOG_TRANSPORT_EMAIL_ENABLED=true
      - GRAYLOG_TRANSPORT_EMAIL_PORT=25
      - GRAYLOG_TRANSPORT_EMAIL_USE_AUTH=false
      - GRAYLOG_TRANSPORT_EMAIL_USE_TLS=false
      - GRAYLOG_TRANSPORT_EMAIL_USE_SSL=false
      - GRAYLOG_TRANSPORT_FROM_EMAIL=youremail@yourdomain.com
      - GRAYLOG_TRANSPORT_SUBJECT_PREFIX=[graylog]
    links:
      - mongodb:mongo
      - elasticsearch
    depends_on:
      - mongodb
      - elasticsearch
    ports:
      # Graylog web interface and REST API
      - 7555:7555
      # Syslog TCP
      - 8514:8514
      # Syslog UDP
      - 8514:8514/udp
      # GELF TCP
      - 12201:12201
      # GELF UDP
      - 12201:12201/udp

Example Version 3:

version: '3'
services:
    # MongoDB: https://hub.docker.com/_/mongo/
    mongo:
      image: mongo:4.2
      networks:
        - graylog
    # Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docker.html
    elasticsearch:
      image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
      environment:
        - http.host=0.0.0.0
        - transport.host=localhost
        - network.host=0.0.0.0
        - "ES_JAVA_OPTS=-Dlog4j2.formatMsgNoLookups=true -Xms512m -Xmx512m"
      ulimits:
        memlock:
          soft: -1
          hard: -1
      deploy:
        resources:
          limits:
            memory: 1g
      networks:
        - graylog
    # Graylog: https://hub.docker.com/r/graylog/graylog/
    graylog:
      image: graylog/graylog:4.2
      environment:
        # CHANGE ME (must be at least 16 characters)!
        - GRAYLOG_PASSWORD_SECRET=somepasswordpepper
        # Password: admin
        - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
        - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
      entrypoint: /usr/bin/tini -- wait-for-it elasticsearch:9200 --  /docker-entrypoint.sh
      networks:
        - graylog
      restart: always
      depends_on:
        - mongo
        - elasticsearch
      ports:
        # Graylog web interface and REST API
        - 9000:9000
        # Syslog TCP
        - 1514:1514
        # Syslog UDP
        - 1514:1514/udp
        # GELF TCP
        - 12201:12201
        # GELF UDP
        - 12201:12201/udp
networks:
    graylog:
      driver: bridge

After starting all three Docker containers by running docker-compose up, you can open the URL http://127.0.0.1:9000in a web browser and log in with username adminand password admin(make sure to change the password later). Change GRAYLOG_HTTP_EXTERNAL_URI=to your server IP if you run Docker remotely.

Configuration

Every configuration option can be set via environment variables.. Simply prefix the parameter name with GRAYLOG_and put it all in upper case.

For example, setting up the SMTP configuration for sending Graylog alert notifications via email, the docker-compose.ymlwould look like this:

version: '2'
  services:
    mongo:
      image: "mongo:4.2"
      # Other settings [...]
    elasticsearch:
      image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
      # Other settings [...]
    graylog:
      image: graylog/graylog:4.2
      # Other settings [...]
      environment:
        GRAYLOG_TRANSPORT_EMAIL_ENABLED: "true"
        GRAYLOG_TRANSPORT_EMAIL_HOSTNAME: smtp
        GRAYLOG_TRANSPORT_EMAIL_PORT: 25
        GRAYLOG_TRANSPORT_EMAIL_USE_AUTH: "false"
        GRAYLOG_TRANSPORT_EMAIL_USE_TLS: "false"
        GRAYLOG_TRANSPORT_EMAIL_USE_SSL: "false"

Another option would be to store the configuration file outside of the container and edit it directly.

CUSTOM CONFIGURATION FILES

Instead of using a long list of environment variables to configure Graylog (see Configuration), you can also overwrite the bundled Graylog configuration files.

The bundled configuration files are stored in /usr/share/graylog/data/config/ inside the Docker container.

Create the new configuration directory next to the docker-compose.ymlfile and copy the default files from GitHub:

mkdir -p ./graylog/config
cd ./graylog/config
wget https://raw.githubusercontent.com/Graylog2/graylog-docker/{{SERVER_VERSION}}/config/graylog.conf
wget https://raw.githubusercontent.com/Graylog2/graylog-docker/{{SERVER_VERSION}}/config/log4j2.xml

The newly created directory ./graylog/config/with the custom configuration files now has to be mounted into the Graylog Docker container.

This can be done by adding an entry to the volumes section of the docker-compose.ymlfile:

version: '2'
services:
  mongodb:
    image: mongo:4.2
    # Other settings [...]
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.0
    # Other settings [...]
  graylog:
    image: graylog/graylog:{{SERVER_VERSION}}
    # Other settings [...]
    volumes:
      # Mount local configuration directory into Docker container
      - ./graylog/config:/usr/share/graylog/data/config
Warning

Graylog is running as USER graylog with the ID 1100
in Docker. That ID need to be able to read the configuration files you place into the container.

Reading individual configuration settings from files

The Graylog Docker image supports reading individual configuration settings from a file. This can be used to secure configuration settings with Docker secrets or similar mechanisms.

This has the advantage, that configuration settings containing sensitive information don’t have to be added to a custom configuration file or into an environment variable in plaintext.

The Graylog Docker image checks for the existence of environment variables with the naming scheme GRAYLOG_&lt;CONFIG_NAME&gt;__FILE
on startup and expects the environment variable to contain the absolute path to a readable file.

For example, if the environment variable GRAYLOG_ROOT_PASSWORD_SHA2__FILE
contained the value /run/secrets/root_password_hash, the Graylog Docker image would use the contents of /run/secrets/root_password_hashas value for the root_password_sha2configuration setting.

Docker secrets

Note

Docker secrets are only available in Docker Swarm services starting with Docker 1.13. Please refer to Manage sensitive data with Docker secrets for more details.

Example for using Docker secrets in a Docker Swarm service:

# Create SHA-256 hash of our password
 echo -n 'password' | sha256sum | awk '{ print $1 }' 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

# Create a Docker secret named "root_password_hash"
  printf '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8' | \
  docker secret create root_password_hash -
    nlujwooo5uu6z0m91bmve79uo

  docker secret ls
    ID                          NAME                 DRIVER              CREATED             UPDATED
    nlujwooo5uu6z0m91bmve79uo   root_password_hash                       34 seconds ago      34 seconds ago

# Create Docker Swarm service named "graylog" with access
# to the secret named "root_password_hash"
  docker service create --name graylog \
     --secret root_password_hash \
     -e GRAYLOG_ROOT_PASSWORD_SHA2__FILE=/run/secrets/root_password_hash \
     -p 9000:9000 graylog/graylog:4.2
    mclk5gm39ingk51s869dc0htz
    overall progress: 1 out of 1 tasks
    1/1: running   [==================================================>]
    verify: Service converged

  docker service ls
    ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
    mclk5gm39ing        graylog             replicated          1/1                 graylog:4.2      *:9000->9000/tcp

Persisting data

In order to make the recorded data persistent, you can use external volumes to store all data. In case of a container restart, this will simply re-use the existing data from the former instances.

Using Docker volumes for the data of MongoDB, Elasticsearch, and Graylog, the docker-compose.ymlfile looks as follows:

version: '2'
services:
  # MongoDB: https://hub.docker.com/_/mongo/
  mongodb:
    image: mongo:4.2
    volumes:
      - mongo_data:/data/db
   # Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docker.html
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
    volumes:
      - es_data:/usr/share/elasticsearch/data
    environment:
      - http.host=0.0.0.0
      - transport.host=localhost
      - network.host=0.0.0.0
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 1g
  # Graylog: https://hub.docker.com/r/graylog/graylog/
  graylog:
    image: graylog/graylog:<SERVER_VERSION>
    volumes:
      - graylog_data:/usr/share/graylog/data
    environment:
      # CHANGE ME (must be at least 16 characters)!
      - GRAYLOG_PASSWORD_SECRET=somepasswordpepper
      # Password: admin
      - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
      - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
    entrypoint: /usr/bin/tini -- wait-for-it elasticsearch:9200 --  /docker-entrypoint.sh
    links:
        - mongodb:mongo
        - elasticsearch
    restart: always
    depends_on:
      - mongodb
      - elasticsearch
    ports:
      # Graylog web interface and REST API
      - 9000:9000
      # Syslog TCP
      - 1514:1514
      # Syslog UDP
      - 1514:1514/udp
      # GELF TCP
      - 12201:12201
      # GELF UDP
      - 12201:12201/udp
# Volumes for persisting data, see https://docs.docker.com/engine/admin/volumes/volumes/
volumes:
  mongo_data:
    driver: local
  es_data:
    driver: local
  graylog_data:
    driver: local

Start all services with exposed data directories:

docker-compose up

Plugins

If you want to add plugins, you can put them into a local directory and mount that directory as a volume. This way, you don’t have to create a new docker image every time you want to add a new plugin (or remove an old one).

Simply create a pluginfolder, download the plugin(s) you want to install into it and mount the directory as a volume into the docker container:

mkdir plugin
wget https://downloads.graylog.org/releases/graylog-integrations/graylog-integrations-plugins-4.2.0.tgz
tar -xvzf graylog-integrations-plugins-4.2.0.tgz graylog-integrations-plugins-4.2.0/plugin/graylog-plugin-integrations-4.2.0.jar --directory plugin
docker run --name graylog --link mongo --link elasticsearch \    
-p 9000:9000 -p 12201:12201 -p 1514:1514 \    
    -e GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9000/" \    
    -v ./plugin:/usr/share/graylog/plugin \    
    -d graylog/graylog:4.2

The docker-compose.ymlwould look like this:

version: '3'
services:
   mongo:
        image: mongo:4.2
        # Other settings [...]
   elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
        # Other settings [...]
   graylog:
        image: graylog/graylog:4.2
        # Other settings [...]
        volumes:
           - <PATH_TO_LOCAL_PLUGIN_DIR>:/usr/share/graylog/plugin

Restart the container and docker will recreate the graylog container with the new volume included:

docker-compose restart graylog

Kubernetes automatic master selection

Running Graylog in Kubernetes opens the challenge to set the is_master=true
setting only for one node in the cluster. The problem can be solved by calculating the name of the pod if Graylog is running in a stafeful set with the following environment variable:

env:
- name: POD_NAME
  valueFrom:
    fieldRef:
      fieldPath: metadata.name

For a stateful set, the name of the first pod in a cluster always ends with -0. See the Documentation about stateful set. The master selection mechanism in docker-entrypoint.sh file does the following:

  • Examine if Graylog is running inside Kubernetes
  • Verify that the pod name ends in -0
  • Set is_master=truefor this container

Nomad automatic master selection

When running Graylog in a Nomad cluster, you must ensure that only one node in the cluster has the setting is_master=truein the server.conf file.

Whether the container is running on Nomad may be identified with an environmetal check on NOMAD_ALLOC_INDEX. Should that variable be set to 0, the container will set Graylog to is_master=true. If the variable is set to anything other than 0 , it will set Graylog to is_master=false.

Troubleshooting

  • In case you see warnings regarding open file limit, try to set ulimit from the outside of the container:
docker run --ulimit nofile=64000:64000 ...
  • The devicemapper
    storage driver can produce problems with Graylogs disk journal on some systems. In this case please pick another driver like aufsor overlay.

Testing a beta version

Caution

We only recommend running pre-release versions if you are an experienced Graylog user and know what you are doing.

You can also run a pre-release (alpha, beta, or release candidate) version of Graylog using Docker.

The pre-releases are tagged in the graylog/graylog Docker image.

See the available tags for the Graylog image on Docker Hub and pick an alpha/beta/rc tag like this:

$ docker run --link mongo --link elasticsearch -p 9000:9000 -p 12201:12201 -p 1514:1514 \
    -e GRAYLOG_HTTP_BIND_ADDRESS="127.0.0.1:9000" \
    -d graylog/graylog:4.1.0-rc.1-2

Was this article helpful?

What's Next