Running Go applications using Docker Compose in GoLand

Posted on by Florin Pățan

Today we’ll be continuing our series on how to use Docker to run and debug Go applications.

In this post, we’ll use Docker Compose to run and debug our application. For this article, we’ll be using the source code here and we’ll switch to the compose branch before we start.

Running Go applications using Docker Compose

Let’s start with running the application using Docker Compose.

Looking at the project we’ve already created, the docker-compose.yaml file might resemble the one found in the repository :

version: "3.5"

services:
  web:
    container_name: dockerdev
    build: ./
    ports:
      - "8000:8000"
    environment:
      DD_DB_HOST: db
    command: /server
    depends_on:
      - db
  db:
    container_name: dockerdev-db
    image: postgres:12.2-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: goland
      POSTGRES_PASSWORD: goland
      POSTGRES_DB: goland
    volumes:
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

In the database section, we need to create a new file called init.sql. The contents of this file are used to set up the database needed for the service to run.

Finally, let’s run the Sync packages of <project> quick-fix in the main.go file to download the pgx library and run the application. This step is needed if you don’t already have version 4.5.0 of pgx in your modules cache.

Running a Docker Compose-based application is similar to other Run Configurations. Click on the double-green arrow button next to the services directive in the docker-compose.yaml. To run just a single service, click on the green arrow next to the service type you want to run, e.g. web or db in our sample configuration above.

Running Docker Compose from the IDE

Once the configuration runs, a new section called Compose will be available in the Services Tool Window under the Docker node.
This will show every suite of Docker Compose services that are running.

Every service definition can be explored, and all running instances are shown for each service. The information available for a container in a Docker Compose service is the same as what’s available for a regular Docker container.

Note: If you are starting heavier services, like a database server, or the services need a bit of initialization time, then your Go service needs to take the startup time of those services into account.
In our example code, this is handled using the getDBConnection function, which attempts to connect to the database a few times with an exponential backoff before giving up.

Restarting a Docker Compose service

After making changes to our code, we need to restart our service to reload these changes. At the moment, using the IDE to restart it is a bit complex, as doing so requires you to take the following steps:

  • Go to Run | Edit Configurations and duplicate the existing Docker Compose configuration.
  • Edit the newly created configuration to add the name of the service that should be restarted, and enable the –build option to force the image to be rebuilt before running it

After you do these steps, you can then stop the existing service, remove the existing container, and then launch the newly created configuration.

Restart Docker Compose service

Pro tip: You can stop and remove the service at the same time using the Delete feature.

Debugging Go applications with Docker Compose

To debug an application using Docker Compose, we need to make changes to both the Dockerfile and docker-compose.yaml files. We can switch to the compose-debug branch of the repository to make this easier to follow.

Now, the docker-compose.yaml file looks like this:

version: "3.5"

services:
  web:
    container_name: dockerdev
    build: ./
    ports:
      - "8000:8000"
      - "40000:40000"
    environment:
      DD_DB_HOST: db
    security_opt:
      - "seccomp:unconfined"
    cap_add:
      - SYS_PTRACE
    command: /dlv --headless --listen=:40000 --api-version=2 exec /server
    depends_on:
      - db
  db:
    container_name: dockerdev-db
    image: postgres:12.2-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: goland
      POSTGRES_PASSWORD: goland
      POSTGRES_DB: goland
    volumes:
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

Note: The important parts here are the security_opt and cap_add properties, as they allow the debugger to run in the Docker environment.

Running this would be similar to running a regular Docker Compose configuration. We can connect to the container with a Go Remote configuration and our debugger session will start just like it would if we were debugging a regular configuration.

Debugging Go Service in Docker Compose

This concludes our article today. We’ve discussed how to use Docker Compose and how to run and debug our application from GoLand.
In the next article, we’ll cover how to use Kubernetes from the IDE and how to run and debug our applications using it.
Please share your feedback with us, either in the comments section below, on our issue tracker, or by tweeting to us @GoLandIDE.

Comments below can no longer be edited.

2 Responses to Running Go applications using Docker Compose in GoLand

  1. Romain says:

    May 8, 2020

    Hello,

    Thanks for this awesome blog post. I’m trying to find a way to debug my tests that are executed on my Docker container. I did found a way but it’s not really convenient :
    1. Start the container and execute “dlv test…”
    2. Start the “Go remote” feature on Goland
    3. Debug my test.

    What I would like to do is to be able to debug a test directly from Goland, using the “Run test” button when I’m in a test file (like it’s possible to do locally).

    Is there a way to launch the “dlv test…” part directly from Goland so that I just need to add my breakpoint and hit the “run test” button to debug it ?

    Thanks !

    • Florin Pățan says:

      May 11, 2020

      Hi Romain,

      Thank you for your feedback.
      At the moment I cannot recommend any solution for this.
      Please watch/vote for https://youtrack.jetbrains.com/issue/IDEA-236730 and then this workflow would be solved.

Subscribe

Subscribe for updates