docker日常使用指南

前言

在对外提供应用程序时,常常碰到运行环境与开发环境不一致的情况,或虽然操作系统一样,但部署时可能碰到一些系统库版本不一样导致运行问题。或对外提供库时,没有客户需要的环境,需要花时间搭建虚拟机。这一些坑,大部分情况下都能通过docker这个工具帮我们方便的解决。因此学习docker是比较有价值的,同时,docker的使用也非常的简单,核心的命令比较少。本文对自己使用中用到的一些方式进行总结,一些理解可能不完全正确,更详细的可以去看官方文档。

1.基础知识

1.1 docker是什么

docker是一种容器技术,是一种沙盒技术。它提供了一种非常遍历的打包机制,这种机制直接打包了应用运行所需要的整个操作系统,从而能够保证本地环境(开发环境)和生产环境(运行环境)的高度一致。

想了解docker更底层技术的,可以去扩展阅读:Cgroups和Namespace技术

扩展阅读2:daemon和client

1.2 与虚拟机(VM)的区别



图的左边,画出了虚拟机的工作原理。其中,名为 Hypervisor 的软件是虚拟机最主要的部分。它通过硬件虚拟化功能,模拟出了运行一个操作系统需要的各种硬件,比如 CPU、内存、I/O 设备等等。然后,它在这些虚拟的硬件上安装了一个新的操作系统,即 Guest OS。

跟真实存在的虚拟机不同,在使用 Docker 的时候,并没有一个真正的“Docker 容器”运行在宿主机里面。Docker 项目帮助用户启动的,还是原来的应用进程,只不过在创建这些进程时,Docker 为它们加上了各种各样的 Namespace 参数。

总而言之:Docker其实共享了宿主机操作系统的内核,因此内核不同的情况下,不能很好的使用docker, 比如windows上想用linux的docker就比较麻烦。Docker相对于VM比较轻量。

1.3 镜像与容器

镜像与容器的关系有点像类与对象的关系,镜像是一个静态概念,容器是一个运行时概念,容器是镜像的实例。通俗的讲,镜像就是放在硬盘上的,而容器是基于镜像跑起来后的东西。

2.安装

以下步骤默认宿主机为Ubuntu, 其它操作系统可以参考官方文档。

快捷安装脚本可通过文末的方式去获得。

2.1 在线安装

安装docker: https://docs.docker.com/engine/install/ubuntu/

sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

验证安装结果:

sudo docker run --rm hello-world

如果宿主机没有显卡或者我们不使用显卡,到这一步就结束了安装,如果要使用显卡,还需要进一步安装 nvidia-docker2:

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#install-guide

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://6kx4zyno.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
EOF sudo systemctl restart docker
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi 可用于验证能否访问GPU

2.2 离线安装

对于宿主机不让联网的时候,可以进行离线安装,也比较方便。

可以参考这篇总结:https://fanfuhan.github.io/2019/11/22/docker_based_use/

3.配置

此节总结几个常见的可能修改的配置。大部分的配置都可以通过修改/etc/docker/daemon.json完成,也有例外。

3.1 镜像存储位置设置

docker镜像默认占用根目录空间,有些时候根目录空间不足,需要指定其他位置。

此时通过修改/etc/docker/daemon.json完成:

{
"data_root":"myownpath", ### 存储位置
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}

执行命令使配置生效(修改daemon.json后都需要执行):

systemctl daemon-reload
systemctl restart docker

3.2 设置镜像源

镜像源是来获取镜像的地方,类似pip源,有时候官方源速度不行或根本访问不了。这时候可以通过设置代理(下节)或设置镜像源的方式去改善。

{
"data_root":"myownpath", ### 存储位置
"registry-mirrors": ["https://6kx4zyno.mirror.aliyuncs.com"], ### 镜像源,可以设置多个
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}

3.3 代理设置

有些时候需要挂代理去下载代码或者镜像。代理的设置分为对daemon的设置(主要影响镜像下载)和client(影响的是容器运行中的)。

3.3.1 daemon代理

docker是一个C/S架构,我们执行的docker命令实际是一种客户端,它会发起REST API到daemon(Server端),由daemon去拉取需要的镜像。此节设置的就是daemon的代理。几乎所有的daemon相关设置都可以在daemon.json中完成,但代理是个例外,这个设置需要创建:

/etc/systemd/system/docker.service.d/http-proxy.conf 文件。

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp" ### 设置一些ip跳过代理

3.3.2 容器代理

创建~/.docker/config.json:

{
"proxies":
{
"default":
{
"httpProxy": "http://192.168.1.12:3128",
"httpsProxy": "http://192.168.1.12:3128",
"noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
}
}
}

还有一种方式是在Dockerfile或启动容器的时候设置环境变量:

4.docker的使用

4.1 基础使用

4.1.1 启动容器(docker run)

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

docker run有比较多的参数可以设置,完整的参见:https://docs.docker.com/engine/reference/commandline/run/

比较常用的是下面一些:

-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
--net=bridge: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--expose=[]: 开放一个端口或一组端口;
--volume , -v: 绑定一个卷
--rm ,退出容器后删除名字
--restart ,重启选项,有no/always/on-failure/unless-stopped
--entrypoint ,重写容器进程的入口

比如我们执行sudo docker run -it --name test ubuntu:16.04就是以前台交互形式,以ubuntu:16.04镜像启动一个容器,第一次运行大概会输出下面这些内容:

Unable to find image 'ubuntu:16.04' locally
16.04: Pulling from library/ubuntu
58690f9b18fc: Pull complete
b51569e7c507: Pull complete
da8ef40b9eca: Pull complete
fb15d46c38dc: Pull complete
Digest: sha256:454054f5bbd571b088db25b662099c6c7b3f0cb78536a2077d54adc48f00cd68
Status: Downloaded newer image for ubuntu:16.04
root@d8324be2d956:/#

也就是第一次运行时,会去拉取镜像,然后启动容器并进入容器终端(也可以通过docker pull 去自己拉取)。进入容器终端,我们就可以像普通终端一样去安装工具,编译代码等等了。

而如果以后台形式运行,则是:

sudo docker run -d --name test ubuntu:16.04
a64fea9800522c5347eaa9feb87ee6c9d67762d81519cc58dbdeec5a8a786066

容器将以后台形式运行。那么我们怎么进入在后台运行的容器呢?

4.1.2 进入容器

进入容器有2种方式,一种是attach, 一种是

docker exec -it 容器ID/名称 bash

推荐使用这种。进入后,可输入exit退出容器终端(只是退出终端,容器并不停止)

4.1.3 停止/删除/启动/重启容器

docker stop 容器ID/名称
docker rm 容器ID/名称 ### 当容器发生重名时,我们就得删除以前的或者把新的改名
docker start 容器ID/名称
docker restart 容器ID/名称

还是非常好理解的,基本上就是英文加容器即可。

还有一个docker update可用于修改docker run时指定的参数。

基本上学会以上操作,就能跑起来一个现场的容器,创建一个隔离的环境了。但仅仅有这些还不够,因为一旦删除容器了,我们在容器里创建的内容都不在了。

4.2 进阶使用

4.2.1 持久化(挂载主机硬盘)

启动时通过-v 主机目录:容器目录选项即可将主机的目录挂载到容器中。

sudo docker run -d --name test -v /home/xxx:/root/xxx ubuntu:16.04

4.2.2 端口映射

有时候容器内启动的是一个网络服务,这个服务去监听一个接口。但它监听的实际上是容器的内部端口,直接去访问是不行的,需要映射一个主机端口到容器的端口。

通过-p 主机端口:容器端口或直接使用主机网络--net=host

docker run -d -p 5000:5000 ubuntu:16.04
docker run -d --net=host ubuntu:16.04

4.2.3 自定义启动命令

截止到目前,我们都没有指定过容器启动后运行什么命令,其实run的最后一个参数可以用于在启动容器后运行的命令:

docker run -d --name test ubuntu:16.04  /bin/bash
docker run -d --name test ubuntu:16.04 sh -c “/run.sh && /bin/bash” ### 多条命令拼接

4.2.4 容器状态/日志查看

> docker ps ###列出当前容器(包括已经停止的)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b8862fc5d600 6e4bffa46d70 "kube-controller-man…" 13 days ago Up 13 days k8s_kube-controller-manager_kube-controller-manager-alg-dev01_kube-system_5af433af822e5ae2fb8825ecf24ac394_11
8ed05c4c9210 ebac1ae204a2 "kube-scheduler --au…" 13 days ago Up 13 days k8s_kube-scheduler_kube-scheduler-alg-dev01_kube-system_8d0b3537ceaac4d2c6bbcb377f490c26_10
f36f7818738b 66f781e54201 "nvidia-device-plugin" 2 weeks ago Up 2 weeks k8s_nvidia-device-plugin-ctr_nvidia-device-plugin-daemonset-d2ct6_kube-system_09c990d8-83a5-4bc5-b8ad-c7bf00079f59_158850
c60e540d83d6 k8s.gcr.io/pause:3.1 "/pause" 2 weeks ago Up 2 weeks > docker logs [-f等选项] 容器名/ID

4.2.5 对容器修改的提交

很多时候我们基于一个镜像启动了容器,在容器中我们安装了我们需要的软件,想在容器删除后也能够使用,而不是再装一次。这时就需要我们能够提交这个修改。和git类似,也是通过commit指令去提交。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

Create a new image from a container's changes

Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)

例如在我们上述启动的ubuntu16.04的容器基础上,我们装了一些软件:

docker commit test ubuntu:my16.04

即可生成一个新的镜像(注意不是容器)。那么下次我们启动时直接用我们生成的这个镜像,启动的容器就包含了我们已经安装过的环境了。

docker run -d --name test ubuntu:my16.04  /bin/bash

4.3 制作镜像(Dockerfile)

4.3.1 Dockerfile编写

通过在容器内修改再提交的方式虽然能够生成镜像,但手动操作太多,而且不便于自动化。更常用的制作镜像的方式是Dockerfile。Dockerfile的基本使用比较简单,只需要掌握几个关键字:

FROM ubuntu:16.04 ### FROM: 基础镜像
ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai ### 设置容器的时区, ENV用于设置环境变量 RUN mkdir /opt/alg ### RUN: 执行一条命令,多个命令可以通过&& ADD config/ /opt/alg/config/ ### ADD: 除有COPY的功能外,还能通过URL下载文件,并且会自动解压缩
COPY Dependency/ /opt/alg/Dependency/ ### COPY: 拷贝宿主机的文件或文件夹到镜像
COPY bin/ /opt/alg/bin/
COPY models/ /opt/alg/models/ ENTRYPOINT ["/opt/alg/config/start_service.sh" ] ### 设置容器启动的入口,类似于main函数,在docker run中可以通过 --entrypoint=XXX 覆盖,如果有这个,那么docker run时设置的command就会被当作它的参数

除了用ENTRYPOINT去指定入口,还可以用CMD去指定,这2者也可能混用。它们之间的差异参考:https://blog.csdn.net/wuce_bai/article/details/88997725

4.3.2 镜像生成

有点类似于我们编译代码,docker提供的生成镜像的命令也是build:

在Dockerfile所在目录执行:

docker build . -t 镜像名:标签
例如:
docker build . -t myapp:v1

镜像生成后,我们就可以使用前文的方式去启动容器了。

4.4 镜像的保存、载入

镜像既可以上传至官方的DockerHub供人pull,也可以自行搭建私有化的镜像仓库(如harbor)。但对于普通人或日常使用,更多的可能是想将镜像保存成一个可传输的文件,然后放到其他机器,再载入。这个docker也是有对应命令支持的。

docker save [OPTIONS] IMAGE [IMAGE...]
> docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3 ###将镜像runoob/ubuntu:v3 保存成my_ubuntu_v3.tar
docker load
--input , -i : 指定导入的文件,代替 STDIN。
--quiet , -q : 精简输出信息。
> docker load -i my_ubuntu_v3.tar

也可以结合其他压缩软件的命令,直接保存出压缩包:

docker save <myimage>:<tag> | gzip > <myimage>_<tag>.tar.gz
gunzip -c <myimage>_<tag>.tar.gz | docker load

4.5 显卡的使用

对于深度学习部署,很多可能需要显卡,使用docker时,需要保证显卡驱动安装,同时按上述步骤安装了nvidia-docker2。

启动容器时,增加--gpus选项即可:

sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi ### all: 所有显卡都可用
sudo docker run --rm --gpus device=0,2 nvidia/cuda:11.0-base nvidia-smi ### 0,2 卡可用
也可以用下列方式:
sudo docker run --rm --gpus '"device=0"' nvidia/cuda:11.0-base nvidia-smi ### 0卡可用

4.6 其他常用指令

docker images 列出所有镜像
docker rmi 删除镜像
docker cp 宿主机和容器间拷贝文件

还有一个不错的工具叫runlike,可以用来查看容器启动时的参数,可自行安装。

5. 使用场景

docker即可以用来发布应用,服务,这可能也是它的一种主要使用场景,也可以用来方便的创建不同的开发编译环境,比如在我们的ubuntu16.04机器上,去开发centos SDK, 甚至它也可以通过vnc去连接,获得图形化的开发环境。

一键快捷安装脚本:

链接:https://pan.baidu.com/s/1tb9tWEMzs6Ms1WDCzf1fqQ

提取码:58q3

若以上链接失效,关注 老司机的视觉屋,回复dockertool即可获取链接

docker日常使用指南的更多相关文章

  1. ubuntu日常使用指南

    目录 换源 开发相关的基本包 vimrc python, pip zsh, oh-my-zsh, josh 配置android相关环境 查看库文件(libxxx.a/libxxx.so,动态静态库均可 ...

  2. 【云计算】ubuntu下docker安装配置指南

    Docker Engine安装配置 以下描述仅Docker在Ubuntu Precise 12.04 (LTS).Ubuntu Trusty 14.04 (LTS).Ubuntu Wily 15.10 ...

  3. TortoiseGit日常使用指南

    本文在介绍了软件安装和设置后, 写了TortoiseGit 常用的一些功能, 包括:创建新库添加文件及文件夹创建分支看分支情况及修改log比较版本差异合并分支其他操作: Stash; 忽略文件本文不包 ...

  4. Docker快速配置指南

    下面是一个跟 Docker 网络相关的命令列表. 其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效. -b BRIDGE or --bridge=BRIDGE --指定容 ...

  5. Linux Mint安装Docker踩坑指南

    我家的服务器选用的Linux Mint系统,最近安装Docker的时候踩了一些小坑,但是总体还算顺利. 我们都知道Linux Mint系统是基于Ubuntu的,说实话用起来感觉还是很不错的,安装Doc ...

  6. Docker - 故障排查指南

    这阵子开始捣鼓 Docker,遇到过不少问题,下面记录下问题以及解决方案 一.Docker 报 Failed to start Docker Application Container Engine ...

  7. Docker 日常指令

    镜像 制作镜像 docker build –t 172.0.0.1/demo/xxx:20180906_002 .[不要忘记 点] 查看镜像 docker images 删除镜像 docker rmi ...

  8. API 文档管理工具 (Yapi) Docker Compose部署指南

    前言介绍 Yapi 由 YMFE 开源,旨在为开发.产品.测试人员提供更优雅的接口管理服务,可以帮助开发者轻松创建.发布.维护 API. 权限管理 YApi 成熟的团队管理扁平化项目权限配置满足各类企 ...

  9. docker 日常操作(会更新)

    搜索镜像 1,命令行中所有命令搜索 docker search centos 2,在官网中搜索镜像 下载镜像 docker pull centos centos后要加:[版本号],如果没有就默认下载l ...

随机推荐

  1. 解决 OnDropFiles 可能无响应的问题【转】

    大多数程序都有接收拖放文件的功能,即是用鼠标把文件拖放到程序窗口上方,符合格式的文件就会自动被程序打开.最近自己对编写的程序增加了一个拖放文件的功能,在 Windows XP.Windows Serv ...

  2. 重定向">" 及">>"符号的简单运用

    1.command > file 将输出重定向(可理解写入)到 file. 2.command >> file  将输出以追加的方式重定向到 file,也就是写入到 file的尾端. ...

  3. 终于有人把Android技术面试知识体系整理出来了,这些学习手册让你的面试稳如泰山

    前言 年年寒冬,年年也挡不住一个安卓程序员追求大厂的决心.想要进入大厂,我们需要掌握哪些知识点呢?这里,我为大家梳理了一个整体的知识架构.整体包括Java.Android.算法.计算机基础等等,相应的 ...

  4. 刷了无数大厂Android研发岗面试题,其实考的无非是这 3 点能力

    前言 发现一个有趣的现象,似乎程序员们对面试题总是抱有热情,多看几道面试题,自己的面试能力就可以提高一点. 作为一个研发工程师,看过很多公司的面试题,也参与过很多公司的面试,发现大厂的面试题更加具有代 ...

  5. Window2016 安装Docker

    测试环境 Windows2016 DataCenter 安装步骤 1.开始运行"PowerShell" 2.指定Tls协议为1.2.(建议都先执行这一条命令,官方文档没有这一步,实 ...

  6. CentOS时间日期类语法

    目录 一.date时间日期类 1. date显示当前时间 2. date 显示非当前时间 3. date 设置系统时间 二.cal 查看日历 一.date时间日期类 date [OPTION]... ...

  7. Java的几种创建实例方法的性能对比(二)

    上一篇里对几种书写方式进行了简单的测试,得出了一些初步的结论.这次简单了解Lambda原理后,对测试做了一些调整,发现得到不一样的结果,而这个调整,明显更契合实际开发的场景. 暂时还没有亲自去验证,主 ...

  8. .NetCore+OpenSSL实现Https

    前言 最近,有时间研究了一下HTTPS安全通信的原理,感兴趣的同学可以看下上一篇博文深入理解Https如何保证通信安全 ,随即联想到近段时间开发的.NetCore项目,.NetCore API应用程序 ...

  9. Docker for windows安装与使用

    1.安装Docker for windows之前,需要将系统的hyper-v功能打开 2.下载Docker for windows进行安装 访问url:https://docs.docker.com/ ...

  10. POSIX多线程编程-条件变量pthread_cond_t

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...