DockerでC++開発環境構築（ubuntu版）

# 概要

C++の学習をする必要があるため、コンパイル＆実行環境をDockerにて作成する。
「[C++初心者がDockerで開発環境をつくってみた](https://qiita.com/kai_kou/items/1f4b9a45a5d4d6788649)」のページを参考に最新の情報で環境を構築してみる。

## 作業における補足

- 本ページでは参照ページのとおり、ubuntuでコンテナを構築してみる
- 今回は学習目的のため、g++でコンパイルが行える環境ができればよい
- イメージ名：cppdev
- コンテナ名：cppdev
- 階層構造は以下のとおり

```
cppdev
 ├ src
 │  └ hello.cpp
 │ 
 ├ Dockerfile
 └ docker-compose.yml
```

# 確認用のC++プログラムを作成
```c++:hello.cpp
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello! World!" << endl;
    return 0;
}
```


# Dockerfile の作成

```:Dockerfile
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
    apt-get install -y build-essential cmake clang libssl-dev vim
```

【補足】

**DEBIAN_FRONTEND=noninteractive**
apt-get でインストールするものの中には対話形式で設定を行うものがある。
Docker だと選択肢に答えようがない（入力できない）のでこの環境変数を設定する。

**apt-get update**
インストール可能なパッケージの「一覧」を更新する。

**apt-get install パッケージ名**
指定したパッケージをインストールする。
-y：問い合わせがあった場合はすべて「y」と答える

**build-essentialパッケージ**
開発に必須のビルドツールを提供しているパッケージ。
gcc(GNU C Compiler)やg++(GNU C++ Compiler), makeなどがインストールされる（らしい）。

**cmake**
コンパイラに依存しないビルド自動化のためのフリーソフトウェア。

**clang**
プログラミング言語 C、C++、Objective-C、Objective-C++ 向けのコンパイラフロントエンド。

**libssl-dev**
何用にインストールが必要なのか調査中。

**vim**
Dockerコンテナに入ってviでファイル編集を行うため。

# docker-compose.ymlの作成

```:docker-compose.yml
version: "3.3"
services:
  cppdev:
    build:
      context: .
      dockerfile: Dockerfile
    image: cppdev
    container_name: cppdev
    volumes:
      - type: bind
        source: .
        target: /cppdev
    stdin_open: true
    tty: true
    working_dir: /cppdev/src/build
```


【補足】
**version: "3.3"**
docker-compose.ymlのファイルフォーマットバージョンを宣言している。※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/)

**build**

　**context**
　Dockerfile を含むディレクトリへのパスを設定 ※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#context)　

　**dockerfile**
　指定されたパスの Dockerfile を使ってビルドを行う。 ※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#dockerfile)　

**image**
build に加えて image も指定した場合、Compose はビルドイメージに名前をつける。　※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#build)　

**container_name**
デフォルトのコンテナー名ではない、独自のコンテナー名を設定する　※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#container_name)

**volumes** ※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#volumes)

　**type**
　マウントタイプを表す。bindは、追加のバインドオプションを設定する。

　**source**
　バインドマウントにおいてはホスト上のパスを指定する。

　**target**
　ボリュームがマウントされるコンテナー内のパスを指定する。

**stdin_open**
「docker container run」のオプションに対応づいている（iオプションに相当）。
コンテナの標準入力とDockerホストの標準入力を接続する。

**tty**
「docker container run」のオプションに対応づいている（tオプションに相当）。
コンテナの標準出力とDockerホストの標準出力を接続する。

**working_dir**
「docker container run」のオプションに対応づいている（wオプションに相当）。
コンテナ内の作業用ディレクトリを指定。


# Dockerイメージ作成＆コンテナ起動

「docker-compose up」コマンドを実行するイメージ作成からコンテナ起動までを行う。

```:Powershell
> docker-compose up -d

Building cppdev
Step 1/3 : FROM ubuntu:20.04
20.04: Pulling from library/ubuntu
d51af753c3d3: Pull complete
fc878cd0a91c: Pull complete
6154df8ff988: Pull complete
fee5db0ff82f: Pull complete
Digest: sha256:8bce67040cd0ae39e0beb55bcb976a824d9966d2ac8d2e4bf6119b45505cee64
Status: Downloaded newer image for ubuntu:20.04
 ---> 1d622ef86b13
Step 2/3 : ENV DEBIAN_FRONTEND=noninteractive
 ---> Running in 340e04446fa3
Removing intermediate container 340e04446fa3
 ---> d3007a31fe0e
Step 3/3 : RUN apt-get update &&     apt-get install -y build-essential cmake clang libssl-dev
 ---> Running in 52dde3806dc8
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [101 kB]
Get:2 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
Get:3 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [3884 B]
Get:4 http://security.ubuntu.com/ubuntu focal-security/universe amd64 Packages [1245 B]
Get:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease [97.0 kB]

・・・省略・・・

Processing triggers for libc-bin (2.31-0ubuntu9) ...
Processing triggers for ca-certificates (20190110ubuntu1) ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
Removing intermediate container 52dde3806dc8
 ---> a75062c81452

Successfully built a75062c81452
Successfully tagged cppdev:latest
WARNING: Image for service cppdev was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating cppdev ... done    
```

【補足】
**-d**
コンテナをバックグラウンドで実行する。

# コンテナ起動後の確認

- Dockerイメージを確認

docker-compose.ymlの「image」で指定した名称でDockerイメージを作成できている。

```:Powershell
> docker image ls

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cppdev              latest              65c31f2d8ba7        6 minutes ago       966MB
ubuntu              20.04               1d622ef86b13        4 days ago          73.9MB
```

- コンテナを確認

docker-compose.ymlの「container_name」で指定した名称でDockerイメージを作成できている。

```:Powershell
> docker container ps -a

CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                   PORTS                    NAMES
e14ee88fd5b3        cppdev                "/bin/bash"              6 minutes ago       Up 6 minutes                                        cppdev
```

- コンテナに入る

```:Powershell
> docker container exec -it cppdev /bin/sh    
# cd /
# ls -la

total 56
drwxr-xr-x   1 root root 4096 Apr 28 16:06 .
drwxr-xr-x   1 root root 4096 Apr 28 16:06 ..
-rwxr-xr-x   1 root root    0 Apr 28 16:06 .dockerenv
lrwxrwxrwx   1 root root    7 Apr 23 11:06 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Apr 15 11:09 boot
drwxrwxrwx   1 root root 4096 Apr 28 16:06 cppdev
drwxr-xr-x   5 root root  360 Apr 28 16:06 dev
drwxr-xr-x   1 root root 4096 Apr 28 16:06 etc
drwxr-xr-x   2 root root 4096 Apr 15 11:09 home
lrwxrwxrwx   1 root root    7 Apr 23 11:06 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Apr 23 11:06 lib32 -> usr/lib32
lrwxrwxrwx   1 root root    9 Apr 23 11:06 lib64 -> usr/lib64
lrwxrwxrwx   1 root root   10 Apr 23 11:06 libx32 -> usr/libx32
drwxr-xr-x   2 root root 4096 Apr 23 11:06 media
drwxr-xr-x   2 root root 4096 Apr 23 11:06 mnt
drwxr-xr-x   2 root root 4096 Apr 23 11:06 opt
dr-xr-xr-x 130 root root    0 Apr 28 16:06 proc
drwx------   2 root root 4096 Apr 23 11:09 root
drwxr-xr-x   1 root root 4096 Apr 24 01:07 run
lrwxrwxrwx   1 root root    8 Apr 23 11:06 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Apr 23 11:06 srv
dr-xr-xr-x  13 root root    0 Apr 27 18:45 sys
drwxrwxrwt   1 root root 4096 Apr 28 16:06 tmp
drwxr-xr-x   1 root root 4096 Apr 23 11:06 usr
drwxr-xr-x   1 root root 4096 Apr 23 11:09 var
```

- サンプルプログラムをコンパイル＆実行

期待した動作をした。

```:Powershell（コンテナに入って実行）
# cd /cppdev/src
# g++ hello.cpp -o hello
# ./hello

Hello! World!
```

# 関連記事

- [DockerでC++開発環境構築（CentOS版）](https://qiita.com/yuzutarogo/items/ced75e288f4712ae55d4)
- [DockerでC++開発環境構築（Alpine版）](https://qiita.com/yuzutarogo/items/d60ba007eae969be53ae)