0%

Docker的使用与总结

在程序开发过程中,经常需要我们去配置各种开发环境,而本地与线上还可能存在环境依赖的不同,导致出现一些不知名的bug,这个时候不要抓头,是时候使用docker来帮你排忧解难了,下面我通过下面几个篇章来介绍Docker.

原理介绍篇

Docker是什么

docker是linux容器的一种封装,提供简单易用的容器使用接口。它是最流行的Linux容器解决方案。

简单来说就是,docker可以将你的环境进行封装,并且程序在docker内运行,有了docker,你就再也不用担心环境问题了。

Docker的优势

更高效的利用系统资源

由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统 资源的利用率更高。

无论是应用执行速度、内存损耗或者文件存储速度,都要比传 统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运 行更多数量的应用。

更快速的启动时间

传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接 运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启 动时间。大大的节约了开发、测试、部署的时间。

一致的运行环境

开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环 境不一致,导致有些 bug 并未在开发过程中被发现。

而 Docker 的镜像提供了除内 核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码 在我机器上没问题啊” 这类问题。

持续交付和部署

对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意 地方正常运行。

使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员 可以通过 Dockerfile 来进行镜像构建,并结合持续集成(Continuous Integration) 系 统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。

而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环 境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

更轻松的迁移

由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在 很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运 行结果是一致的。

因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一 个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

安装篇

一般,如果使用GPU,一般要安装Docker, Nvidia-Docker,Docker-Compose,Nvidia-Docker-Compse

Docker的安装

参考官方安装链接: https://docs.docker.com/install/linux/docker-ce/ubuntu/

按官方教程docker ce(community edtion),并按教程测试docker是否成功安装。比如我们以Ubuntu Xenial 16.04 (LTS)为例:
下载Docker安装包,在这里https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/挑选最新的Docker版本。
安装:sudo dpkg -i /path/to/package.deb
测试:sudo docker run hello-world
(可选)Linux环境下的权限变更,这样不用每次docker命令都加sudo,自己没服务器权限找管理员变更。

Nvidia-Docker 的安装

参考官方安装链接: https://github.com/NVIDIA/nvidia-docker

nvidia-docker已经升级到nvidia-docker2,本测试是在nvidia-docker 1.0基础上完成的,1.0的安装方法请看上面教程链接。

Test nvidia-smi with the latest official CUDA image

docker run –runtime=nvidia –rm nvidia/cuda nvidia-smi

docker-compose的安装

参考官方安装链接:https://docs.docker.com/compose/install/

https://github.com/docker/compose/releases下载linux版本。
重命名为docker-compose并放到/usr/local/bin/下面
增加执行权限:sudo chmod +x /usr/local/bin/docker-compose
测试: docker-compose –version

nvidia-docker-compose的安装

sudo pip install nvidia-docker-compose

注意:nvidia-docker-compose和nvidia-docker2不兼容,如果安装了nvidia-docker2,那就不需要安装这个compose了

使用篇

使用容器必然需要容器镜像,镜像是容器环境的存储形式。容器的运行要从镜像开始。

如何构建镜像?

1.简单方法,docker pull

dockerhub上面存在很多别人上传好的镜像,如果有合适的可以自己从上面直接拉,很方便。命令如下:

1
docker pull pytorch/pytorch:1.3-cuda10.1-cudnn7-runtime

2.在docker内直接安装

如果在dockerhub上面拉下来的镜像满足了你大部分的需求,但是缺少了几个环境怎么办呢?可以在已经拉下来的镜像中直接安装,安装完对应的库之后,commit就可以了。

例子如下:

在ubuntu容器中安装vim后保存。

1
2
3
4
5
docker run -it ubuntu   # 运行docker
yum install -y vim # 安装vim
exit # 退出
docker container ls -a # 查看容器,找到刚才安装后的容器
docker commit 059fdea031ba chaoyu/centos-vim # 提交容器,前面参数是id,后面参数是名字

但是这种方式不推荐,因为安装了哪些东西,容易忘记,不好复现

3.通过Dockerfile安装

Dockerfile可以帮助你解决2中,时间长,容易忘记,不好复现的问题,通过Dockerfile,你可以从你的基础镜像开始,一步一步的安装,得到最终的结果。

就像下面这样:

1
2
3
4
5
6
7
8
9
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz

下面是构建Dockerfile常用命令的一些解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
FROM ubuntu:14.04 #带有tag的base image

LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
LABEL maintainer=“yc_uuu@163.com"

#对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
RUN yum update && yum install -y vim \
Python-dev #反斜线换行
RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”

WORKDIR /app #相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd
RUN pwd # 打印结果应该是/test/demo

ADD and COPY
ADD hello / # 把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录
ADD test.tar.gz / # 添加到根目录并解压

WORKDIR /root
ADD hello test/ # 进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
COPY hello test/ # 等同于上述ADD效果

ADD与COPY
- 优先使用COPY命令
-ADD除了COPY功能还有解压功能
添加远程文件/目录使用curl或wget

ENV # 环境变量,尽可能使用ENV增加可维护性
ENV MYSQL_VERSION 5.6 # 设置一个mysql常量
RUN yum install -y mysql-server=“${MYSQL_VERSION}”

构建好Dockerfile之后,就可以使用下面的命令构建镜像了

1
2
docker build -t [docker name] .
docker build --network=host -t [docker name] . ### 修改网络,使用本机网络,如果有些库安装的时候下载不下来可以试试这个参数。

镜像的运行

1.启动一个bash终端,允许用户进行交互

1
2
3
4
5
6
7
8
9
10
11
12
docker run --rm -it -v $HOME/history:/history/ dockername /bin/bash  

或者指定运行网络为主机网络:

docker run --net=host --rm -it -v $HOME/history:/history/ pytorch:nightly-gpu /bin/bash

# --name 给容器定义一个名称
# -i 让容器的标准输入保持打开。
# -t 让Docker分配一个伪终端,并绑定到容器的标准输入上。
# -v 将本机路径映射到容器中,实现在容器中的操作。
# /bin/bash 指定docker容器,用shell解释器交互。

2.利用docker-compose运行docker服务

上面1中的命令好长,如果映射多个路径岂不很麻烦,而且启动容器后,没有办法与本地文件进行交互,有没有更方便的使用容器的方法?当然有

使用docker-compose,docker-compose可以实现本地文件到docker内的映射,这样你在本地直接修改程序,docker内就同步修改了,比较方便。

使用docker-compose首先要创建docker-compose.yml文件,参考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# yml配置文件格式版本为2, 镜像名字为webspring
version: '2'
services:
webspring:
build: . # 如果没有下面image的镜像,默认在当前路径下的Dockerfile运行
image: tf-demo/docker:0.0.1 # 默认运行的镜像
# 映射端口
shm_size: '2gb' ## 代表交换空间,可省略
ports:
- "8888:8888"
- "8887:6006"
# 映射文件路径
volumes:
- .:/app

创建好后,运行下面的命令启动服务就可以啦。

1
docker-compose run --rm  webspring bash

停止容器

1.在运行的容器中,使用exits退出
2.直接将对应的docker stop掉

这里一般先使用docker ps查看docker的运行情况,然后使用 docker stop xxxx 来将对应的容器停止掉。

记得经常去清一下缓存(很重要):

1
docker rm $(docker ps -qf status=exited)

发布到仓库

docker提供了一个类似于github的仓库docker hub,官方网站(需注册使用)
https://hub.docker.com/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 注册docker id后,在linux中登录dockerhub
docker login

# 注意要保证image的tag是账户名,如果镜像名字不对,需要改一下tag
docker tag haha/vim springwang/vim
# 语法是: docker tag 仓库名 springwang/仓库名

# 推送docker image到dockerhub
docker push springwang/vim:latest

# 去dockerhub中检查镜像
# 先删除本地镜像,然后再测试下载pull 镜像文件
docker pull springwang/vim:latest

保持到本地

  1. 保存镜像
1
2
docker save imageID > filename
docker load < filename
  1. 保存容器
1
2
docker export containID > filename
docker import filename [newname]

多用户使用docker

1
2
3
4
5
6
7
8
9
10
1. 创建docker用户组
sudo groupadd docker

2. 应用用户加入docker用户组
sudo usermod -aG docker ${USER}
3. 重启docker服务
sudo systemctl restart docker

4.查看docker信息
docker info

Docker 常用命令总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker search  hello-docker  # 搜索hello-docker的镜像
docker search centos # 搜索centos镜像
docker pull hello-docker # 获取centos镜像
docker run hello-world #运行一个docker镜像,产生一个容器实例(也可以通过镜像id前三位运行)
docker image ls # 查看本地所有镜像
docker images # 查看docker镜像
docker image rmi -f hello-docker # 删除centos镜像
docker ps #列出正在运行的容器(如果创建容器中没有进程正在运行,容器就会立即停止)
docker ps -a # 列出所有运行过的容器记录
docker save centos > /opt/centos.tar.gz # 导出docker镜像至本地
docker load < /opt/centos.tar.gz #导入本地镜像到docker镜像库
docker stop `docker ps -aq` # 停止所有正在运行的容器
docker rm `docker ps -aq` # 一次性删除所有容器记录
docker rmi `docker images -aq` # 一次性删除所有本地的镜像记录
docker container ls -a # 检查运行中的容器
docker tag id new_name # 重命名docker images
docker system prune # 清楚docker缓存

其他

  1. dockerignore容易被.gitignore给忽略掉,所以需要使用如下代码上传才行:
    1
    git add -f .dockerignore
  2. 在pycharm中使用docker进行操作:https://zhuanlan.zhihu.com/p/27114995