Docker超详细基础教程

2022-04-13 11:44:43 远鉴IT外包 547
一、docker概述
1.什么是docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)。
 
简单来说,docker是一个用来装应用的容器,就像杯子可以装水,笔筒可以放笔,书包可以放书,可以把深度学习放在docker中,可以把网站放入docker中,可以把任何想得到的程序放在docker中。
 
2.docker思想
2.1 集装箱
如果没有集装箱,运输货物的时候,东西零散容易丢失,但是一旦有了集装箱,那么货物就会被装载在里面,运输的时候就不容易丢失了。目前我们需要将程序部署到一台新的机器上,可能会启动不起来,比如缺失库或者配置文件等。那我们如果将程序想象成货物,我们只需要用一个集装箱将这些程序打包好,就可以在部署后保证程序可以正常运行,而docker就是这个集装箱。
 
2.2 标准化
运输方式:
 
如果我们把台式机的应用部署到服务器上,我们可能选择用移动硬盘拷过去,而有了docker,我们就可以将这个过程标准化。
docker运输东西通过一个超级码头,任何地方需要货物都由鲸鱼先送到超级码头,然后再由鲸鱼从超级码头把货物送到目的地。
在刚才例子中,我们只需要在台式机执行一个docker命令,把鲸鱼派过来,把程序送到超级码头去,再在服务器上执行一个docker命令,然后由鲸鱼把程序从超级码头送到服务器上去。
 
存储方式:
 
当我们把程序存储到服务器上时,因为下次我们有可能还要修改存储目录,所以我们需要记住这个目录。而有了docker之后我们就不用记住了程序在哪里了,我们使用的时候只需要一条命令就行了。
 
API接口:
 
docker提供了一系列rest api的接口,包含了对docker也就是对我们的应用的一个启动停止查看删除等等。有了docker,通过docker命令就可以对其进行操作。
 
2.3 隔离
我们在使用虚拟机时有自己的cpu、硬盘、内存,完全感觉不到外面主机的存在。docker也差不多,不过它更轻量,我们创建虚拟机可能要几分钟,但是docker只需要一秒。最底层的技术是linux一种内核的限制机制,叫做LXC。
LXC是一种轻量级的容器虚拟化技术,最大效率的隔离了进程和资源。通过cgroup、namespace等限制,隔离进程组所使用的物理资源,比如CPU,MEMORY等等。这个机制在7、8年前已经加入到linux内核了,直到2013年docker出世的时候才火起来,大家可能奇怪为什么这么好的技术埋没这么多年都没人发现呢?
英雄造时势,时势造英雄,如果没有云计算、敏捷开发、高频度的弹性伸缩需求,没有IT行业这么多年长足的发展,也就没有docker。
 
3.为什么选择docker? 
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
 
更高效的利用系统资源。
更快速的启动时间
一致的运行环境
持续交付和部署
更轻松的迁移
更轻松的维护和扩展
4.走进docker
镜像就是上面说的集装箱,仓库就是超级码头,容器就是我们运行程序的地方。docker运行程序的过程,就是去仓库把镜像拉到本地,然后用一条命令把镜像运行起来变成容器。
build:构建,就是构建镜像.
ship:运输,运输镜像,从仓库和主机运输.
run:运行的镜像就是一个容器.
build,ship,run和镜像,仓库,容器是一一对应的。
 
4.1 镜像
镜像的英文名叫image。前面我们讲到了集装箱,鲸鱼拖着的所有集装箱就是一个镜像。
 
从本质上来说镜像就是一系列文件,可以包括我们应用程序的文件,也可以包括我们应用的运行环境的文件。既然是文件,那么是以什么样的格式在本地保存的呢?
 
说到存储格式,就要提到linux的一个存储技术,叫做联合文件系统。它是一种分层的文件系统,可以将不同的目录挂到同一个虚拟文件系统下。
 
比如test1下有三个文件夹,test2下有两个文件夹,还有一个readme文件。联合文件系统就是可以在一个文件夹(test)中看到多个文件夹(test1,test2)中的内容。
 
通过这种方式可以实现文件的分层,test1可以把它看作第一层,test2可以把它看作第二层。每一层有每一层自己的文件,docker就是利用了这种分层的概念实现了镜像存储。
 
镜像的存储格式如下图所示。
 
 
 
这张图是分层的。最下面一层,上面也是一层层的好像集装箱罗列在一起。这就是镜像最直观的存储方式。下面是操作系统的引导,上面是linux操作系统,再上面是一些相关的软件。如果是我们自己的程序,就可以是tomcat,jdk,再往上是应用代码。每一层是我们自己都可以控制得,最上面一层先忽略不看,因为这是和容器有关的。注意一点,docker镜像系统的每一层都是只读的,然后把每一层加载完成之后这些文件都会被看成是同一个目录,相当于只有一个文件系统。docker的这种文件系统被称之为镜像。
 
4.2 容器
为了便于理解,大家可以把容器想象成虚拟机。每个虚拟机都有自己的文件系统,可以把上图整个一部分看成是文件系统,与虚拟机系统的区别是这里面的文件系统是一层一层的,并且最下面的n层都是只读的,只有上面一层是可写的。为什么要有可写的这层呢?大家的程序运行起来,势必会要写一些日志,写一些文件,或者对系统的某一些文件做一些修改,所以容器在最上面一层创建了可读可写的文件系统。
 
因为镜像的每一层都是只读的,所以在程序的运行过程中要写镜像文件时,它会把文件的每一层拷到文件的最上层,然后再对它进行修改。修改之后,当我们的应用读一个文件时会从顶层进行查找,如果没有才会找下一层。
 
由于容器的最上一层是可以修改的,镜像是不能修改的,这样就能保证镜像可以生成多个容器独立运行,没有任何干扰。
 
4.3 仓库
我们的镜像是要在其它机器上运行,如何进行传输呢?
 
这就用到了docker仓库,我们要先把我们的镜像传到docker仓库中,再由目的地把docker仓库拉过去,这就完成了这样的一次传输过程。
 
谁提供了这样的仓库呢?docker自己提供了hub.docker.com。但是非常慢为了解决这个问题,国内很多公司也在做自己的仓库。
 
二、docker安装
因为在虚拟机中安装的是linux的redhat7.4,所以接下来将介绍如何在redhat中安装docker。以下方法通用于linux内核,只是安装包有可能不同。
 
安装需满足以下要求:
 
64位操作系统
3.1及以上的Linux内核
iptables版本在1.4及以上
git版本在1.7及以上
A ps executable, usually provided by procps or a similar package.
XZ Utils 4.9 or higher
A properly mounted cgroupfs hierarchy; a single, all-encompassing cgroup mount point is not sufficient.
通过 uname -r 命令查看你当前的内核版本。
 
1.在线安装
1.1 如果安装过请先卸载
yum remove docker \
           docker-client \
           docker-client-latest \
           docker-common \
           docker-latest \
           docker-latest-logrotate \
           docker-logrotate \
           docker-engine
1.2 安装依赖设置yum仓库
安装依赖:
 
yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
 设置仓库:
 
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
1.3 安装docker
yum install docker-ce docker-ce-cli containerd.io
1.4 启动并加入开机启动
systemctl start docker
 
systemctl enable docker
1.5 验证是否安装成功 
docker version
 
docker run hello-world
能够看到输出 Hello from Docker! 就OK了!
 
2.离线安装
在某些情况下,我们可能需要离线安装docker,那么接下来将详细介绍如何实现docker的离线安装。
 
2.1 下载docker压缩包
从download.docker.com下载对应的docker包,我这里下载的是docker-18.03.1-ce.tgz版本,如果有需要可以直接私信我。
 
2.2 解压文件
[root@devops-102 ~]# tar -xvzf docker-18.03.1-ce.tgz 
2.3 将文件移动到系统目录下 excutable path。
ps:本步骤为可选步骤,也可以把解压路径放到PATH变量中。 
 
$ sudo cp docker/* /usr/bin/
执行后会看到 API listen on /var/run/docker.sock 的提示,表示docker已经在运行了。
 
2.4 启动Dockerd
$ sudo dockerd &
2.5 验证
$ sudo docker run hello-world
 能够看到输出 Hello from Docker! 就OK了!
 
2.6 设置开机自启动
systemctl start docker       
 
systemctl enable docker
三、docker基础操作
当我们安装好docker后,由于我做深度学习方面的研究,所以我们需要安装相应的深度学习环境,以配置pytorch环境为例,接下来会一步步介绍如何构建一个属于自己的镜像。
 
1.镜像基本操作
1.1 抓取镜像
首先我们进入dockerhub网站选择一个我们需要的镜像。
 
 
 
 然后输入:
 
docker pull pytorch/pytorch
通过此命令可以docker远程仓库拉取镜像到本地。
 
docker pull [options] NAME[:TAG]
 
name是拉取镜像的名称;TAG表示是可选的,如果不选表明时latest,如果选择表明是指定版本的。
options是拉去的一些参数,当不加请求地址的时候回去docker的官网拉取镜像。
 
1.2 查看镜像
docker images 
 通过此命令可以查看当前存在哪些镜像。
 
 
 
docker images [options] [REPOSITORY[:TAG]]
 
options是选项,后面是指定镜像的名称。这个用的不多,可能当本地镜像非常多的时候要指定查看某一个镜像。
IMAGE ID 其实是一个64位的字符串,它可以唯一标识我们的镜像,这里只显示了16位,后面的被截掉了
 
1.3 启动交互式容器
docker run -it -v /home/admin/workplace:/workspaces --name bert_pytorch pytorch/pytorch /bin/bash
docker run -t -i -v 本地目录:虚拟目录 --name 自定义名称 IMAGE_NAME /bin/bash
 
-i –interactive=true | false,默认是false
-t –tty=true | false,默认是false
–name 给启动的容器自定义名称,方便后续的容器选择操作
启动交互式的容器,就是类似虚拟机、云主机的操作方式,操作完一个命令后仍然可以继续
 
1.4 删除镜像
docker rmi d77dc4c8ebab
docker rmi 镜像的标识
 
标识可以是id或者name。
 
2.容器的操作
2.1 运行容器
# 简单操作
docker run 镜像的标识|镜像名称[tag]
# 常用的参数
docker run -d -p  宿主机端口:容器端口 --name 容器名称 镜像的标识|镜像名称[tag]
# -d: 代表后台运行容器
# -p: 宿主机端口:容器端口: 为了映射当前Linux的端口和容器的端口
# --name 容器名称: 指定容器的名称
 
2.2 查看正在运行的容器
docker ps [OPTIONS]
# OPTIONS说明:
# -a: 代表查看全部的容器,包括没有运行
# -q: 只查看容器的标识
# -f: 根据条件过滤显示的内容
# --format: 指定返回值的模板文件
# -l: 显示最近创建的容器
# -n: 列出最近创建的n个容器
# --no-trunc: 不截断输出
# -s: 显示总的文件大小
 
2.3 查看容器的日志 
docker logs -f 容器id
 
# -f: 可以滚动查看日志的最后几行
 
2.4 进入到容器内部
docker exec -it 容器id bash
 
2.5 删除容器(删除容器前,需要先停止容器)
docker stop 容器id
# 停止指定的容器
docker stop $(docker ps -qa)
# 停止全部容器
docker rm 镜像id
# 删除指定容器
docker rm $(docker ps -qa)
# 删除全部容器
 
2.6 启动容器
docker start 容器id
 
3.构建镜像
 构建Docker镜像,可以保存对容器的修改,并且再次使用。构建镜像提供了自定义镜像的能力,以软件的形式打包并分发服务及其运行环境。Docker中提供了两种方式来构建镜像:
 
通过容器构建:docker commit
通过Dockerfile:docker build
3.1 使用commit命令构建镜像
docker commit 7843e0556e67 bertpytorch
命令:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
 
参数:
-a,–author=“”,指定镜像的作者信息
-m,–message=“”,提交信息
-p,–pause=true,commit时是否暂停容器
 
 
 
3.2 使用Dockerfile文件构建镜像
Docker允许我们利用一个类似配置文件的形式来进行构建自定义镜像,在文件中可以指定原始的镜像,自定义镜像的维护人信息,对原始镜像采取的操作以及暴露的端口等信息。比如:
 
# Sample Dockerfile
FROM ubuntu:16.04
MAINTAINER wgp "Kingdompin@163.com"
RUN apt-get update
RUN apt-get install -y nginx
EXPOSE 80
命令:docker build [OPTIONS] DockerFile_PATH | URL | -
 
参数:
 –force-rm=false
–no-cache=false
–pull=false
-q,quite=false,构建时不输出信息
–rm=true
 -t,tag=“”,指定输出的镜像名称信息
 
4.镜像迁移
我们制作好的镜像,一般会迁移到其他机器上。Docker提供了几种镜像迁移分享给其他人的方式。推荐镜像迁移应该直接使用Docker Registry,无论是直接使用Docker Hub还是使用内网私有Registry都可以。使用镜像频率不高,镜像数量不多的情况下,我们可以选择以下两种方式。
 
4.1 上传Docker Hub
首先,需要在Docker Hub上申请注册一个帐号(人机验证时需要科学上网)。然后我们需要创建仓库,指定仓库名称。
 
在终端中登录你的Docker Hub账户,输入docker login,输入用户名密码即可登录成功。
 
查看需要上传的镜像,并将选择的镜像打上标签,标签名需和Docker Hub上新建的仓库名称一致,否则上传失败。给镜像打标签的命令如下。
 
docker tag <existing-image> <hub-user>/<repo-name>[:<tag>]
 
其中existing-image代表本地待上传的镜像名加tag,后面<hub-user>/<repo-name>[:<tag>]则是为上传更改的标签名,tag不指定则为latest。
 
接下来,我们利用push命令直接上传镜像。
 
docker push <hub-user>/<repo-name>:<tag>
 
我们已经上传成功。由于之前介绍的分层存储系统,我们这里是直接对已有的ubuntu镜像进行上传,只是重新打了标签,所以真正上传的只是变化的部分。
 
4.2 导出文件互传
Docker 还提供了 docker load 和 docker save 命令,用以将镜像保存为一个tar文件。比如这次我们将bertpytorch:latest这个镜像保存为tar文件。
 
docker save -o bertpytorch.tar bertpytorch
docker save -o <仓库名称>-<tag>.img <仓库名称>:<tag>
 
查看本地磁盘,即可看见名为bertpytorch的tar包。我们可以将其拷贝给其他机器,再利用load命令重新导入。
 
docker load --input bertpytorch.tar
docker save --input <tar>
 
四、常用linux操作
1.文件和目录
cd /home 进入 '/ home' 目录' 
cd .. 返回上一级目录 
cd ../.. 返回上两级目录 
cd 进入个人的主目录 
cd ~user1 进入个人的主目录 
cd - 返回上次所在的目录 
 
pwd 显示工作路径 
 
mkdir dir1 创建一个叫做 'dir1' 的目录' 
mkdir dir1 dir2 同时创建两个目录 
mkdir -p /tmp/dir1/dir2 创建一个目录树 
 
rm -f file1 删除一个叫做 'file1' 的文件' 
rmdir dir1 删除一个叫做 'dir1' 的目录' 
rm -rf dir1 删除一个叫做 'dir1' 的目录并同时删除其内容 
rm -rf dir1 dir2 同时删除两个目录及它们的内容 
 
cp file1 file2 复制一个文件 
cp dir/* . 复制一个目录下的所有文件到当前工作目录 
cp -a /tmp/dir1 . 复制一个目录到当前工作目录 
cp -a dir1 dir2 复制一个目录 
cp -r dir1 dir2 复制一个目录及子目录
 
linux涉及到docker的基础命令会不断更新,建议收藏,不时查阅!!!
 
如果该文章对您有所帮助,麻烦点赞,关注,收藏三连支持下!
 
各位的支持和认可,是我创作的最大动力!