标签: Docker , C++ 文|吴羽舒

1 前言

之前使用Vagrant管理基于虚拟机的各种开发环境,如今换成Docker。换的原因主要是Docker的网络更快,使用更简单。

先要安装Docker for Mac(DfM),然后启动docker作为守护进程(右上角状态栏会有docker图标)。

查看docker版本信息:

$ docker version

Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b
 Built:             Wed Mar 11 01:21:11 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       afacb8b
  Built:            Wed Mar 11 01:29:16 2020
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

各个安装组件信息:

$ docker --version
Docker version 19.03.8, build afacb8b

$ docker-compose --version
docker-compose version 1.25.4, build 8d51620a

$ docker-compose --version
docker-compose version 1.25.4, build 8d51620a

2 镜像(image)

$ docker image ls
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
$ docker search centos
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
centos                             The official build of CentOS.                   5906                [OK]
$ docker image pull centos:centos6
centos6: Pulling from library/centos
ff50d722b382: Pull complete
Digest: sha256:dec8f471302de43f4cfcf82f56d99a5227b5ea1aa6d02fa56344986e1f4610e7
Status: Downloaded newer image for centos:centos6
docker.io/library/centos:centos6

$ docker image ls
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
centos                    centos6             d0957ffdf8a2        12 months ago       194MB

获得此虚拟机镜像(CentOS 6)后,后续容器可以基于此镜像进行操作。

3 容器(container)

$ docker container run -i -t centos:centos6 /bin/bash
[root@8ba5db58d1bb /]# uname -a
Linux 8ba5db58d1bb 4.19.76-linuxkit #1 SMP Thu Oct 17 19:31:58 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8ba5db58d1bb        centos:centos6       "/bin/bash"         3 minutes ago       Up 3 minutes                            jovial_wilson

按Ctrl-PQ组合键,退出容器的同时保持容器运行。 -d 则以守护进程形式启动容器, -it 是交互形式。

重新进入正在运行的容器:

$ docker container exec -it sharp_heyrovsky bash
[root@2f86d1decff3 /]# uptime
 13:24:46 up  2:11,  0 users,  load average: 0.00, 0.04, 0.01

停止/删除容器:

$ docker container stop  sharp_heyrovsk
$ docker container rm  sharp_heyrovsk

4 持久化数据(base on container id/name)

Docker镜像是由松耦合的只读镜像层组成,一旦容器关闭,重新启动新的容器,新的容器是没有之前保存的文件的。

$ docker image inspect centos:centos6  # 查看镜像信息
$ docker container exec -it sharp_heyrovsky bash
Error response from daemon: Container 2f86d1decff3050b10919703f2a00167eed5bd46a90b1da3626048ff0b53c602 is not running

其实每个容器实例都有自己的id,可以根据id或者name重新启动之前的容器,对应的文件都保存在里面:

$ docker container ls -a        # 查看多有历史容器实例的id等信息
$ docker container start 5045721d1878
$ docker container exec -it 5045721d1878 bash

在将容器实例删除之前,容器里面的数据是不会丢失的,但一旦容器实例被删除,随带着数据也就删除了。

5 基于卷(volume)的持久化数据

不想数据随着容器的删除而消失,需要使用和容器解耦的Docker卷来进行持久化。

创建卷:

$ docker volume create devsrc
devsrc

$ docker volume ls
DRIVER              VOLUME NAME
local               devsrc

$ docker volume inspect devsrc
[
    {
        "CreatedAt": "2020-03-30T15:00:28Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/devsrc/_data",
        "Name": "devsrc",
        "Options": {},
        "Scope": "local"
    }
]

创建容器并挂载卷:

$ docker container run -d -i -t --name mydev --mount source=devsrc,target=/devsrc centos:centos6

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
eee253808301        centos:centos6       "/bin/bash"         38 seconds ago      Up 38 seconds                           mydev

$ docker container exec -it mydev bash

$ [root@eee253808301 /]# ls -ld /devsrc
drwxr-xr-x 2 root root 4096 Mar 30 15:00 /devsrc

同一个卷可以在不同的容器实例中同时被挂载,进行数据的交互,但要程序里面自己控制读写冲突。

6 commit创建新镜像快照

在Docker Hub获取的镜像是很小的,只有基本的操作系统部分,需要安装系列软件包等,安装后可以创建一个新的镜像,这样下次就可以直接使用这个镜像创建新的容器了。

$ docker container stop mydev

$ docker commit -m "c++ dev" mydev centos:mydev    # 还可以包含其他信息,如作者
sha256:e315980591309fa8d10e7a23664e7f3aed35dd201978a7cb280699a7aa6e31bf

$ docker image ls
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
centos                    mydev               e31598059130        42 seconds ago      1.16GB
centos                    centos6              470671670cac        2 months ago        237MB

可以看到新创建的镜像已经存在了,大小也增加了。还可以只是新增tag,而还是同一个镜像。

7 挂载本地目录

在创建一个容器的时候,可以挂载本地目录,但如果为已经存在的容器挂载本地目录,则可以先提交新的镜像,然后创建新的容器并挂载本地目录。

$ docker container run -d -i -t --name mydev2 --user root -p 2200:22 --privileged=true --cap-add=SYS_PTRACE --cap-add=SYS_TIME --security-opt seccomp=unconfined -v /Users/MyDev/Code:/Code --mount source=devsrc,target=/devsrc centos:mydev /bin/bash

$ docker container ls 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
ae6dc97f1d0d        centos:mydev       "/bin/bash"         40 seconds ago      Up 38 seconds       0.0.0.0:2200->22/tcp    mydev2

这样宿主机和容器之间共享目录了。

8 导出,导入,保存,加载

打包容器:

$ docker export --help

Usage:	docker export [OPTIONS] CONTAINER

Export a container's filesystem as a tar archive

Options:
  -o, --output string   Write to a file, instead of STDOUT

$ docker export -o mydev.tar ae6dc97f1d0d

导入容器:

$ docker import --help

Usage:	docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

Import the contents from a tarball to create a filesystem image

Options:
  -c, --change list       Apply Dockerfile instruction to the created image
  -m, --message string    Set commit message for imported image
      --platform string   Set platform if server is multi-platform capable

保存镜像:

$ docker save --help

Usage:	docker save [OPTIONS] IMAGE [IMAGE...]

Save one or more images to a tar archive (streamed to STDOUT by default)

Options:
  -o, --output string   Write to a file, instead of STDOUT

$ docker save -o mydev-centos.tar 470671670cac

加载镜像:

$ docker load --help

Usage:	docker load [OPTIONS]

Load an image from a tar archive or STDIN

Options:
  -i, --input string   Read from tar archive file, instead of STDIN
  • 导出的容器再导入,是没有之前的信息。
  • 保存的镜像再加载,是包含之前的信息。

9 安装devtools-2

$ wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtools-2.repo

$ yum install devtoolset-2-gcc devtoolset-2-binutils devtoolset-2-gcc-c++ -y

$  /opt/rh/devtoolset-2/root/usr/bin/g++ --version
g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15)

临时编译前使用:

export CC=/opt/rh/devtoolset-2/root/usr/bin/gcc
export CPP=/opt/rh/devtoolset-2/root/usr/bin/cpp
export CXX=/opt/rh/devtoolset-2/root/usr/bin/c++

针对特定gcc编译器版本编译。

10 结语

至此,基本满足目前自己的需求,够用了。