C++で書いたプログラムを、docker-composeで立ち上げたUbuntu 18.04で動かして、macOS上のCLionからデバッグする。

タイトルのとおりです。

(普通にkqueueで良いんじゃないのと思いはしたものの、)Linuxのepollシステムコールを使ってソケット処理を書こうとするとどうなるのかを試してみたかったのですが、手元にあったマシンがmacOSだったので、ちょうど最近業務でも使い始めたがまだ慣れていないdocker-composeで開発環境を用意してみようとやってみました。

軽い気持ちでやり始めたものの、なんだかんだで結構ハマったのでメモを残します。

やろうと思えば、docker-composeの操作もすべてCLion上で完結できるようですが、なんかうまくいかないことがあったので、docker-compose startとかはコンソール上でやって、デバッグの部分だけCLionでやってます。

(一応公式ヘルプに使い方 Docker - ヘルプ | CLion が書いてありましたが)

また、以下のソースはリポジトリ GitHub - rkmathi/dockerfiles に置いてます。

動作環境は

な感じです。

とりあえず、CLionなのでまずは CMakeLists.txt を用意しました。

cmake_minimum_required(VERSION 3.0)

set(CMAKE_VERBOSE_MAKEFILE OFF)

set(out_dir ${CMAKE_BINARY_DIR}/out)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${out_dir})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${out_dir})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${out_dir})

project(work)

enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CXX_EXTENSIONS OFF)
ADD_COMPILE_OPTIONS(-Werror -Wall -Wextra)

add_executable(work main.cc)

main.cc も最初なので適当です。

#include <iostream>

int main() {
  std::cout << "main.cc" << std::endl;
  return 0;
}

Dockerfile は、イロイロなところを見ながら次のようにしました。 流石にプロダクション環境で使うことは全く想定していないので、rootユーザにパスワードログインしちゃいます。

FROM ubuntu:18.04

# Configure working directory
ADD . /work
WORKDIR /work

# Install packages
RUN apt-get update && \
  apt-get upgrade -y && \
  apt-get install -y build-essential cmake gcc g++ gdb gdbserver openssh-server rsync

# Enable ssh for root user
# see also: https://docs.docker.com/engine/examples/running_ssh_service/
RUN mkdir /var/run/sshd && \
  echo 'root:root' | chpasswd && \
  sed -i 's/#\?PermitRootLogin prohibit-password/PermitRootLogin yes/'   /etc/ssh/sshd_config && \
  sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

# Expose port for ssh & gdbserver
EXPOSE 22 7777

# Run sshd
CMD ["/usr/sbin/sshd", "-D"]

docker-compose.yml は、こんな感じです。 本当は version: '3'の部分はマイナーバージョンまで指定したほうが良いのかもしれないですがまだ良くわかってないので一旦適当になってます。

version: '3'
services:
  ubuntu-gdbserver:
    build: .
    security_opt: # For gdb debugging
      - seccomp:unconfined
      - apparmor:unconfined
    ports:
      - "7776:22" # For ssh
      - "7777:7777" # For gdbserver
    volumes:
      - .:/work

1. ↑で用意したubuntu-gdbserverサービスを立ち上げておく。

$ docker-compose build ubuntu-gdbserver
$ docker-compose start ubuntu-gdbserver

この後、 ssh root@localhost -p 7776 を試してSSHできることを確認した。 (パスワードは↑のままセットアップしたなら root )

2. CLionを開いて、Docker integrationプラグインをインストールする。

3. Preferences → Build, Execution, Deployment → Toolchainsから追加する。

Nameは何でも良いが、Nameの隣の入力欄は Remote Host にする。

4. Preferences → Build, Execution, Deployment → CMakeから追加する。

ここもNameは何でも良い

5. CLion上で適当にbrake pointをはる

6. Debug実行するときのターゲットで、さっき作ったToolchain選択する。

f:id:rkmathii:20190501155103p:plain

7. Debug実行すると、ちゃんとremote debugできるようになる。

f:id:rkmathii:20190501155231p:plain

おわり