Linux基础—Docker入门和实战
1.为什么使用docker
在docker出现以前,项目的部署:
-
部署速度很慢
-
成本非常高
-
资源浪费
-
难于迁移和扩展
-
可能会被限定硬件厂商
后来出现了虚拟机:
-
一个物理机可以部署多个app
-
每一个app独立运行在一个vm中
但是虚拟化也是有局限性的,每一个虚拟机都是一个完整的操作系统,要分配系统资源,虚拟机多道一定程度时,操作系统本身资源也就消耗殆尽,或者说必须扩容
docker和虚拟机的区别
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
2.配置环境的难题
让开发人员最头疼的麻烦事之一就是环境配置了,每台计算机的环境都不相同,应该如何确保自己的程序换一台机器能运行起来呢?
用户必须确保的是:
-
操作系统的相同
-
各种平台库和组件的安装
-
例如python依赖包,环境变量
如何一些低版本的依赖模块和当前环境不兼容,那就头疼了。。。。。
如果环境配置这么痛苦的话,换一台机器,就得重新配置一下,那么在安装软件的时候,带着原始环境一模一样的复制过来。
解决方案一
虚拟机也可以制作模板,基于模板创建虚拟机,保证环境问题一致
虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。
-
资源占用多
虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。
-
冗余步骤多
虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。
-
启动慢
启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。
解决方案二
自从用上docker容器后,可以实现开发、测试和生产环境的统一化和标准化。
镜像作为标准的交付件,可在开发、测试和生产环境上以容器来运行,最终实现三套环境上的应用以及运行所依赖内容的完全一致。
由于虚拟机的诸多问题,Linux发展出了另一种虚拟化技术:Linux容器(Linux Containers,缩写LXC)
Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。在正常进程的外面套了一个保护层,对于容器里面进程来说,它接触的资源都是虚拟的,从而实现和底层系统的隔离。
-
启动快
容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程,而不是启动一个操作系统,速度就快很多。
-
资源占用少
容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用所有资源。另外,多个容器可以共享资源,虚拟机都是独享资源。
-
体积小
容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小得多。
3.docker容器的优势
更高效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统 资源的利用率更高。 无论是应用执行速度、内存损耗或者文件存储速度,都要比传 统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运 行更多数量的应用。
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接 运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启 动时间。大大的节约了开发、测试、部署的时间。
一致的运行环境
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环 境不一致,导致有些 bug 并未在开发过程中被发现。 而 Docker 的镜像提供了除内 核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码 在我机器上没问题啊” 这类问题。
持续支付和部署
对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意 地方正常运行。 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员 可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系 统进行集成测试, 而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。 而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环 境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在 很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运 行结果是一致的。 因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一 个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
二、docker的相关概念
docker的三大基本
容器中的三个基本概念:
-
镜像:image
-
容器:container
-
仓库:repository
1.docker镜像(images)
Docker镜像就是一个只读的模板。
我们想像一下, 其实镜像就是一个系统的复制文件,就比如我们装系统用的镜像文件,但是又不同于它。通过镜像我们可以创建docker容器。
Docker还提供了一个很简单的机制来创建或更新现有的镜像,用户甚至可以直接从其他人哪里下载一个已经做好的镜像来直接使用。
image的分层存储:
因为镜像包含完整的root文件系统,体积是非常庞大的,因此docker在设计时按照Union FS的技术,将其设计为分层存储的架构。 镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成。
docker镜像的增删改查
-
docker search 镜像名:去docker hub 搜索有关镜像文件
-
docker pull 镜像名:下载docker镜像
-
docker images:查看本地有哪些docker镜像,同docker image ls
-
docker rmi 镜像id或者镜像名:删除本地docker镜像
-
docker rmi -f 镜像id:强制删除镜像文件
docker search centos #去docker hub 搜索有关centos的镜像文件 docker pull centos #下载docker镜像 centos docker pull hello-world #获取一个hello-world镜像 docker images #查看本地有哪些docker镜像 docker image ls #命令同上 docker rmi 镜像id或者镜像名 #删除本地docker镜像 docker rmi -f 镜像id #强制删除镜像文件
2.docker容器(container)
image和container的关系,就像面向对象程序设计中的 类和实例一样,镜像是静态的定义(class),容器是镜像运行时的实体(object)。
容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
注意
-
镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
-
docker容器中必须有进程在后台运行,否则容器挂掉!!!
-
docker镜像每次运行 都会生成新的容器id记录!!!
docker容器的增删改查
-
docker run 镜像名/镜像id:运行处容器进程实例
-
docker ps:查看正在运行的容器进程
-
docker ps -a:显示所有运行过的容器进程(正在运行的,以及挂掉的容器进程),同docker container ls -a,旧的命令
-
docker run -it 镜像id/镜像名 /bin/bash:运行一个交互的容器
-
参数:-i:interactive,交互式的命令操作;-t:terminate,开启一个终端界面 ;/bin/bash:指定linux的解释器
-
-
docker rm 容器id:删除容器id记录,只能删除挂掉的容器
-
docker rm `docker ps -aq` :批量删除停止运行的容器记录
-
docker exec -it 运行着的容器id /bin/bash:进入一个正在运行着的容器
-
docker logs 容器id:查看容器的日志
-
docker logs -f 容器id:检查容器内的日志
3.docker仓库(repository)
仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
公开仓库
最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快读的访问。
私有仓库
当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下载在另外一台机器上使用这个镜像时候,只需需要从仓库上pull下来就可以了。
注意:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。
公有仓库和私有仓库见docker实战部分。
4.docker registry
Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服 务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务 供用户管理私有镜像。
最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并 拥有大量的高质量的官方镜像。
除此以外,还有 CoreOS 的 Quay.io,CoreOS 相 关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像 使用的就是这个服务。
镜像加速器
由于某些原因,在国内访问这些服务可能会比较慢。 国内的一些云服务商提供了针 对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见 的有 阿里云加速器、DaoCloud 加速器、灵雀云加速器等。 使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提高很多。在后 面的章节中会有进一步如何配置加速器的讲解。 国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓 库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。
三、centos安装docker
1.官方安装姿势
教程如下:
1.卸载旧版本
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine
2.设置存储库
yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
3.安装社区版本
yum install docker-ce
4.启动关闭docker
systemctl start docker
docker版本
Docker 是一个开源的商业产品,有两个版本:社区版(Community Edition,缩写为 CE)和企业版(Enterprise Edition,缩写为 EE)。 企业版包含了一些收费服务,个人开发者一般用不到。本文的介绍都针对社区版。
系统环境:
docker最低支持centos7且在64位平台上,内核版本在3.10以上 [root@oldboy_python ~ 10:48:11]#uname -r 3.10.0-693.el7.x86_64
2.阿里云yum源安装
因为官方的安装方式是从国外的网站下载,速度太慢,这里我们选择阿里云的yum源来安装docker。
关于阿里云的yum源配置,详见我之前的博客。配置好后直接安装。
yum install docker -y
启动docker
systemctl start docker
检查docker的运行状态
docker version
配置镜像下载加速器
在contos终端中执行:
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
这个命令是修改/etc/docker/daemon.json文件,写入一个json数据如下
[root@s20 ~]# cat /etc/docker/daemon.json {"registry-mirrors": ["http://f1361db2.m.daocloud.io"]} # 配置好了docker加速器,下载镜像就快很多了
注意:有的人使用这个命令后会出问题,这个问题可以通过修改这个json文本,去掉最后的逗号,即可。
四、docker实战练习
1.活着的容器
容器是否处于运行激活状态是看容器中是否有进程在进行,如果没有,容器会立即关闭。
这里我们实现一个运行着的容器,具体代码很简单。
docker run -d centos /bin/sh -c "while true;do echo '熊大真棒'; sleep 1;done" -d:daemonize,后台运行 centos:指定哪个镜像 /bin/sh:指定linux的解释器 -c:指定一段shell代码 "while true;do echo '熊大真棒'; sleep 1;done",每秒打印一个
当利用docker run来创建容器时,Docker在后台运行的标准操作包括
-
检查本地是否存在指定的镜像,不存在就从公有仓库下载。
-
利用镜像创建并启动一个容器,分配一个文件系统,并在只读的镜像层外面挂在一层可读写层。
-
从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去。
-
从地址池配置一个ip地址给容器,执行用户指定的应用程序,执行完毕后容器被终止。
2.自定义docker镜像
在实际工作中,当我们的运行环境需要迁移时,如果我们在别的计算机中,一项一项的来配置需要的环境,是一件很麻烦的事情。
docker就提供了我们快速导出当前运行的自定义环境,发送给他人,从而快速搭建起项目运行所需要的环境镜像。
步骤如下:
1.获取一个centos镜像,运行出容器实例
docker run -it centos /bin/bash
2.进入容器空间,默认是没有python3和其他软件的
[root@superdesktop ~]# docker run -it 9f3 [root@4595c3de8418 /]# vim # 默认没有vim bash: vim: command not found # 我们安装一个vim yum install vim -y
3.退出容器,提交这个容器为一个新的镜像
exit docker ps -a # 查看刚才安装了vim的容器id,这里 4595c3de8418 9f3 # 这里我的查到时459
提交镜像语法:docker commit 容器id 新的镜像名字
docker commit 459 centos-vim
4.查看提交的镜像文件
docker images
5.导出镜像文件到指定的文件,注意为压缩文件
docker save centos-vim > /opt/centos-vim.tar.gz
6.在本地测试导入这个镜像,可以先删除我们生成的镜像
docker rmi centos-vim # 导入镜像 docker load < /opt/centos-vim.tar.gz
8.为导入的镜像,修改名字
docker tag 旧的镜像名 以docker仓库id开头/新的镜像名
docker tag 84d mydocker/centos-vim
9.执行docker镜像,运行出容器,查看是否携带了vim
docker run -it mydocker/centos-vim vim # 成功的话,vim可以执行
3.docker运行一个flask框架的脚本
下载training/webapp的镜像,用来运行python的flask项目。
docker run的特点,如果镜像不存在,则自动去docker pull下载,
1.通过training/webapp实例一个容器对象:
docker run -d -P training/webapp python app.py -d 后台运行 -P 端口映射,随机映射 training/webapp 镜像名 python app.py 你要执行的命令
2.查看运行容器的端口
docker port 容器id [root@superdesktop ~]# docker port 0ca 5000/tcp -> 0.0.0.0:32768
3.容器的启停命令
docker start 容器id
docker stop 容器id
4.根据端口映射,查看flask框架
访问:192.168.16.122:32768
五、Dockerfile学习
镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础。我们之前的例子都是使用来自docker hub的镜像,直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。
获取docker镜像的方法;
-
去docker仓库获取的方式,一个是公网仓库,一个是私有仓库 docker pull
-
获取别人发来的镜像,也就是自定义的镜像
-
通过dockerfile构建docker镜像
镜像的定制就是定制每一层所添加的配置、文件。如果可以吧每一层修改、安装、构建、操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令 构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
这里我们先学习一下Dockerfile中的功能性参数。
1.Dockerfile文件详解
-
执行系统版本
FROM scratch # 制作base image 基础镜像,尽量使用官方的image作为base image FROM centos # 使用base image FROM ubuntu:14.04 # 带有tag的base image
-
定义dockerfile一些参数的指令
LABEL version=“1.0” # 容器元信息,帮助信息,Metadata,类似于代码注释 LABEL maintainer=“yc_uuu@163.com"
-
在dockerfile中运行操作的指令RUN
RUN yum update && yum install -y vim \ Python-dev # 反斜线换行 RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”
-
切换目录WORKDIR
WORKDIR /root # 相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd WORKDIR /test # 如果没有就自动创建 WORKDIR demo # 再进入demo文件夹 RUN pwd # 打印结果应该是/test/demo
-
添加命令ADD
语法:ADD 本地的资料 容器内的存放路径
ADD除了有添加的作用,同时有解压缩的作用
ADD hello.txt / # 把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录 ADD test.tar.gz / # 添加到根目录并解压,自动的解压test.tar.gz 解压为test
-
复制命令COPY
copy就是把本地的文件,拷贝到容器空间内,没有解压作用
COPY hello test/ # 把hello文件复制到容器中的test目录下
ADD与COPY:
-
优先使用COPY命令
-
ADD除了COPY功能还有解压功能
添加远程文件/目录使用curl或wget
-
ENV:环境便令,使用ENV增加可维护性
ENV MYSQL_VERSION 5.8 # 设置一个mysql常量 RUN yum install -y mysql-server=“${MYSQL_VERSION}” RUN yum install -y mysql-server=“${MYSQL_VERSION}”
2.通过Dockerfile定制一个python flask的web程序
1.准备flask代码
touch flask-test.py vim flask-test.py # coding:utf8 from flask import Flask app=Flask(__name__) @app.route('/') def hello(): return "我是一个flask测试文件" if __name__=="__main__": app.run(host='0.0.0.0',port=8080)
2.准备Dockerfile文件,写入如下内容
touch Dockerfile # 注意:文件名是固定的,首字母大写 vim Dockerfile FROM centos COPY CentOS-Base.repo /etc/yum.repos.d/ COPY epel.repo /etc/yum.repos.d/ RUN yum clean all RUN yum install python-setuptools -y RUN easy_install -i https://pypi.tuna.tsinghua.edu.cn/simple flask COPY flask-test.py /opt/ WORKDIR /opt EXPOSE 8080 # 暴露容器内的8080端口 CMD ["python","flask-test.py"] # 让容器执行如下命令
3.准备文件,构件docker镜像
在/opt/DjangoProject下新建了一个dockerfile-test文件夹
[root@superdesktop dockerfile-test] # ls CentOS-Base.repo Dockerfile epel.repo flask-test.py
其中Centos-Base.repo和epel.repo是阿里云的yum源文件
4.构件docker镜像命令,相对路径在Dockerfile同级下执行
docker build .
5.构建镜像完成后,查看镜像文件
docker images
docker tag 6f0 flask-docker
6.运行这个镜像并访问测试
docker run -d -p 7777:8080 6f0 # -p 可以指定端口来映射
访问192.168.16.122:7777来访问这个flask文件
3.外部访问容器
容器中可以运行网络应用,但是要让外部也可以访问这些应用,可以通过-p或-P参数指定端口映射。
-P 参数会随机映射端口到容器开放的网络端口
docker run -d -P training/webapp python app.py
查看映射端口
docker ps -l # 或者 docker port 容器id
也可以通过-p参数指定映射端口
docker run -d -p 9000:5000 training/webapp python app.py
指定端口后,通过访问9000进行连接
六、docker仓库管理
docker仓库和git的代码仓库是相似的原理,git上用来管理我们的代码,而docker仓库用来管理我们的镜像。
1.公有仓库的发布
1.docker提供了一个类似于github的仓库dockerhub
网址:https://hub.docker.com/需要注册使用
2.注册docker帐号,在linux中登录dockerhub
docker login
注意:
注意要保证image的tag是账户名,如果镜像名字不对,需要改一下tag
docker tag centos-vim mydocker/centos-vim
语法: docker tag 镜像名 仓库名/镜像名
3.推送到docker image到dockerhub仓库
docker push mydocker/centps-vim:latest
4.在dockerhub检查镜像
https://hub.docker.com/
5.删除本地镜像,测试下载pull镜像文件
docker pull mydocker/centos-vim
2.私有仓库
公有仓库是公开的,其他人也可以下载,因此我们还可以使用docker registry官方提供的私有仓库。
1.官方提供的私有仓库registry
https://yeasy.gitbooks.io/docker_practice/repository/registry.html
2.centos下载registry并启动
私有仓库会被创建在容器的/var/lib/registry下,因此通过-v参数将镜像文件存储到本地的/opt/data/registry下 端口映射容器中的5000端口到宿主机的5000端口
docker run -d \ -p 5000:5000 \ -v /opt/data/registry:/var/lib/registry \ registry
3.检查启动的registry容器
docker ps
4.测试连接容器
telnet 192.168.16.122 5000
5.可以查看私有仓库的api数据地址,如下
http://192.168.16.122:5000/v2/_catalog # 浏览器访问
6.私有仓库不支持http方式推送,需要修改默认配置文件
1.编辑docker的配置文件 vim /etc/docker/daemon.json 2.写入如下信息,地址改成你自己的ip {"registry-mirrors": ["http://f1361db2.m.daocloud.io"], "insecure-registries":["192.168.16.122:5000"] } 3.修改docker的配置文件 vim /lib/systemd/system/docker.service 第二步:添加如下配置,在[Service]的代码区域块中,添加如下参数 [Service] EnvironmentFile=-/etc/docker/daemon.json 4.重新加载这个文件 systemctl daemon-reload 5.重启整个docker服务 systemctl restart docker 6.重新启动一个私有仓库 docker run --privileged=true -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry 参数解释: --privileged=true docker容器的安全机制:设置特权级运行的容器
7.修改本地镜像的名字,以仓库地址开头
docker tag 你要修改的镜像 修改之后的镜像名
docker tag fce 192.168.16.122:5000/hello-world
8.推送本地的镜像到私有仓库
docker push 192.168.16.122:5000/hello-world # 再次查看私有仓库内容 http://192.168.16.122:5000/v2/_catalog
9.从私有仓库下载镜像使用
docker pull 192.168.16.122:5000/hello-world