Docker基础上手学习笔记

Docker 全程干货 基于CentOS7

基于CentOS7的Docker

为什么使用Docker?

环境配置难题,软件开发最大麻烦,操作系统设置,各种库和组件的安装。且某些依赖过时与当前环境不兼容,也会带来问题。
应用部署问题,组件较多,运行环境复杂。不同软件集成起来过程有很多不可控的风险,依赖关系复杂,也易出现兼容性问题。由于开发、测试、生产环境的差异,一旦重新迁移服务器或者重新部署环境,还需要重新执行。

如何解决?

将软件和环境一同打包。

Docker如何解决依赖的兼容问题?

将应用的Bins/Libs与应用一起打包,将每个应用放到一个隔离容器去运行,避免互相干扰

Docker如何解决不同系统环境的问题?

Docker将用户程序与所需要调用的系统函数库一起打包
Docker在运行到不同操作系统时,直接通过内核创建虚拟的操作系统实例(内核和库),来隔离不同的进程和资源。

什么是Docker

Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像
Docker应用运行在容器中,相互隔离
Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可在任意Linux操作系统上运行

Docker的用途

提供一次性的环境。如本地测试他人的软件、持续集成时提供单元测试和构建的环境
提供弹性的云服务。Docker容器可随开随关,适合动态扩容和缩容
组建微服务架构。通过多个容器,一台机器可跑多个服务,本机可模拟出微服务架构

Docker与虚拟机

Docker

Docker容器技术是操作系统级的虚拟化,即直接通过内核创建虚拟的操作系统实例(内核和库),来隔离不同的进程和资源,多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行。
Docker容器不需要额外的虚拟机管理软件和虚拟机操作系统层,直接在宿主机操作系统层面上实现虚拟化,从而达到轻量级,高效的目的。

虚拟机

带环境安装的另一种解决方案,它可以在一种操作系统里面运行另一种操作系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一样,而对底层系统来说,虚拟机就是个普通文件,对其他系统毫无影响。
虚拟机属于完全虚拟化,模拟完整的底层硬件环境特权指令的执行,客户操作系统无需进行修改。
虚拟机的缺点:

  1. 资源占用多
  2. 冗余步骤多,需要经过繁琐的配置
  3. 启动慢

Docker的组成

镜像(Image)

Docker把应用程序及其依赖,打包在image文件里。只有通过这个文件才能生成Docker容器
image文件才可以看作是容器的模板,除了提供容器运行时所需要的程序、库、资源、配置等,还包含了一些运行时准备的一些配置参数
Docker根据image文件生成容器的实例,同一个image文件可生成多个同时运行的容器实例
镜像不包含任何动态数据,其内容在构建之后也不会被改变。
一个image文件可以继承另一个image文件
image文件通用,一般来说为节省时间,应尽量使用别人制作的image文件,基于别人的image文件进行加工。
为方便共享,image文件制作完成后,可上传到网上仓库。

容器(Container)

镜像和容器的关系,类似面向对象程序设计中的类和实例,镜像是静态的定义,容器是镜像运行时的实体。
容器是独立运行的一个或一组应用,以及它们的运行态环境,容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行与属于自己的独立的命名空间。容器可以拥有自己的root文件、自己的网络配、自己的进程空间,甚至自己的用户ID空间
容器内的进程是运行在一个隔离的环境里,就好像是一个独立于宿主的系统下操作。这种特性使得容器封装的应用比直接在宿主运行更安全。

仓库(Repository)

Docker镜像的托管平台
镜像创建完成,可在当前宿主机上运行,但如果在其他服务器上使用这个镜像,就需要一个集中的存储、分发镜像的服务。
一个Docker Registry中可包含多个仓库(Repository),每个仓库可包含多个标签,每个标签对用一个镜像。
一个仓库会包含一个软件不同版本的镜像,而标签常用于对应该软件的各个版本,通过<仓库>:<标签>的格式来指定具体是这个软件的哪个版本的镜像。
以Ubuntu镜像为例,ubuntu是仓库的名字,其包含有不同版本标签,如18.04,20.04.如果忽略了标签,则视为lastest作为默认标签。

Docker架构

客户端(client):通过命令或RestAPI向Docker服务端发送指令。可在本地远程向服务端发送指令
服务端(server):Docker守护进程,负责处理Docker指令,管理镜像和容器

Docke安装和镜像操作

  1. 卸载旧版本Docker(可选)
yum remove docker \
                 docker-client \
                 docker-client-latest \
                 docker-common \
                 docker-latest \
                 docker-latest-logrotate \
                 docker-logrotate \
                 docker-selinux \
                 docker-engine-selinux \
                 docker-engine \
                 docker-ce
  1. 安装yum工具
yum install -y yum-utils \
           device-mapper-persistent-data \
           lvm2 --skip-broken
  1. 更新yum本地软件源
yum-config-manager \
   --add-repo \
   https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' 
/etc/yum.repos.d/docker-ce.repo
yum makecache fast
  1. 安装Docker
yum install -y docker-ce
  1. Docker使用中会涉及到各种端口,为了方便使用最好关闭防火墙
# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld
  1. 查看docker版本
docker -v
  1. 配置Docker国内镜像加速(可选),添加链接描述
  2. 启动Docker
systemctl start docker  # 启动docker服务
systemctl stop docker  # 停止docker服务
systemctl restart docker  # 重启docker服务

在这里插入图片描述

镜像名称

  • 一个仓库会包含同一个软件不同版本的镜像
  • 镜像名称一般分两部分组成:[仓库名]:[标签],如果不给出标签,将以 latest 作为默认标签

如:redis:6

镜像操作

  • 访问DockerHub搜索镜像,https://hub.docker.com/,搜索redis、mysql
  • 拉取镜像:docker pull redis
  • 查看本地镜像:docker images
  • 将镜像导出到磁盘:docker save -o 文件名称 镜像名称/ID
  • 删除本地镜像:docker rmi 镜像名称/ID
  • 导入镜像:docker load -i 文件名称

Docker容器

Docker容器操作命令

  • docker run 新建并启动容器
  • docker start/stop/pause/unpause 启动/停止/暂停/恢复容器
  • docker exec 进入容器执行命令
  • docker logs 查看容器运行日志
  • docker ps 查看容器的状态
  • docker rm 删除指定容器
Nginx容器示例

拉取nginx镜像 docker pull nginx
创建并启动容器 docker run --name mynginx -d -p 80:80 nginx
输入后,有一串容器启动的id或编号
–name:指定容器名称
-p:将宿主机端口与容器端口映射,格式:宿主机端口:容器端口
-d:后台运行容器

输入宿主机的ip(CentOS7下额ens33对应的ip地址),到浏览器,访问到nginx

Redis容器示例

拉取redis镜像 docker pull redis
创建并启动容器 docker run --name myredis -d -p 6379:6379 redis
进入容器:docker exec -it myredis bash
root@xxxxx: /data# ,进入到容器id为xxxxx的bash
精简的Linux系统,只包含redis需要的依赖和必要文件
-it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
bash:进入容器后执行的命令
进入容器后执行:redis-cli,使用redis客户端操作redis
127.0.0.1:6379
redis是一个键值对格式的数据库,类似数据结构中的字典

Docker数据卷

容器中的数据问题

一个容器运行一段时间,产生数据,如日志、数据库、新改的配置文件等等,如果数据文件存放在容器中,删除容器时,也会将这些数据删除
docker中,提供了一种存储数据的方法,数据卷,达到数据共享

数据卷基本概念

“数据卷”Data Volumes理解成“宿主机中的目录”,当把某个卷和容器中的某个目录建立映射关系后,就相当于把宿主机中的某个目录和容器中的某个目录建立了映射关系
数据卷提供了很多有用的特性:

  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
  • 对数据卷的更新不会影响镜像,解耦开应用和数据;
  • 卷会一直存在,直到没有容器使用,可以安全地卸载它。

数据卷操作示例

创建数据卷:docker volume create testA;
查看数据卷:docker volume ls
查看对应卷的详细信息:docker volume inspect testA
在linux的docker主机中创建一个卷时,其在宿主机对应的目录(挂载点)路径为/var/lib/docker/volumes/卷名/_data

挂载卷

在创建容器时,可以通过–volume或 -v 参数挂载一个数据卷到某个容器目录
docker run --name testAcon -v testA:/data -d redis
上述命令表示创建一个名为testAcon的容器,将testA卷映射到testAcon容器的/data目录中
注意:如果卷映射的目录在容器中不存在时,会自动在容器中创建对应的目录
一个容器可以使用多个卷,只需要多次使用-v选项指定即可
docker run --name testBcon -v testA:/data -v testB:/var/log -d redis
当指定的卷不存在时,docker会自动创建对应的卷,上述命令中的testB数据卷会被自动创建

绑定挂载

前面创建的数据卷都存放在/var/lib/docker/volumes目录中,这个目录是固定的,它们都能被docker volume命令管理。
docker还有一种映射宿主机目录的方法,这种方法被称之为”绑定挂载”,绑定挂载能够将指定的宿主机目录挂载到容器中,只需要将卷名替换成宿主机上的目录路径即可
docker run -d --name testAcon -v /root/test1:/data1 redis
上述命令将宿主机的/root/test1目录映射到容器的/data1目录中绑定挂载不会生成任何卷,它直接将指定的宿主机目录映射到容器中,所以,docker volume命令无法查看或管理到绑定挂载的路径

官方建议使用卷,而不是绑定挂载,但是,绑定挂载有一个优势,就是绑定挂载可以直接将宿主机中的文件(非目录)直接挂载到容器中,比如,将宿主机中的/etc/localtime文件映射到容器中的/etc/localtime文件
docker run -d --name testAcon -v /etc/localtime:/etc/localtime alpine
通常,使用绑定挂载就是为了将宿主机中的配置文件挂载到容器中,如果是整个目录的数据,建议使用卷,卷只能映射目录,不能映射文件。

nginx示例

创建容器并挂载数据卷到容器内的HTML目录
docker run --name myng -v html:/usr/share/nginx/html -p 80:80 -d nginx
进入html数据卷所在位置,并修改HTML内容
cd /var/lib/docker/volumes/html/_data
ls
vim index.html
修改html文件,在对应的宿主机ip上显示网址信息(需注意对应的容器的端口号)

Docker自定义镜像

为什么要自定义镜像

对于Docker用户来说,最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等都有现成的Docker官方镜像或其他人和组织创建的镜像,我们只需要稍作配置就可以直接使用。某些情况下我们也不得不自己构建镜像,比如:

  • 找不到现成的镜像,比如自己开发的应用程序。
  • 需要在镜像中加入特定的功能

镜像的内部结构

如果只是使用镜像,当然不需要了解镜像的内部结构,直接通过docker命令下载和运行就可以了,但如果我们想创建自己的镜像,或者想理解Docker为什么是轻量级的,就非常有必要学习这部分知识了。

  • 下载官方hello-world镜像:docker pull hello-world
  • 运行:docker run hello-world

Dockerfile

Dockerfile是镜像的描述文件,定义了如何构建Docker镜像,hello-world的Dockerfile:
FROM scratch:表示镜像从白手起家,从0开始构建。
COPY hello/将文件“hello”复制到镜像的根目录。
CMD[“/hello”]容器启动时,执行/hello。
镜像hello-world中就只有一个可执行文件“hello”,其功能就是打印出“Hello from Docker …”等信息

base镜像

hello-world虽然是一个完整的镜像,但它并没有什么实际用途。
通常来说,我们希望镜像能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。这样的镜像我们称作base镜像。
base镜像有两层含义:(1)不依赖其他镜像,从scratch构建;(2)其他镜像可以以之为基础进行扩展。
能称作base镜像的通常都是各种Linux发行版的Docker镜像,比如Ubuntu、Debian、CentOS等。
下载CentOS镜像: docker pull cento

为何系统镜像如此之小

Linux操作系统由内核空间和用户空间组成
内核空间是kernel, Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。
用户空间的文件系统是rootfs,包含我们熟悉的 /dev、/proc、/bin等目录。
对于base镜像来说,底层直接用Host的kernel,自己只需要提供rootfs就行了。
一个精简的OS, rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他Linux发行版,CentOS的rootfs已经算臃肿的了,alpine还不到10MB。

CentOS的Dockerfile

base镜像提供的是最小安装的Linux发行版,CentOS镜像的Dockerfile的内容
ADD指令添加到镜像的tar包就是CentOS 7的rootfs。在制作镜像时,这个tar包会自动解压到/目录下,生成/dev、/proc、/bin等目录。
可在Docker Hub的镜像描述页面中查看Dockerfile。

Docker支持运行多种Linux OS

不同Linux发行版的区别主要就是rootfs。
比如Ubuntu 14.04使用upstart管理服务,apt管理软件包;而CentOS 7使用systemd和yum。这些都是用户空间上的区别,Linux kernel差别不大。所以Docker可以同时支持多种Linux镜像,模拟出多种操作系统环境。
Debian和BusyBox(一种嵌入式Linux)上层提供各自的rootfs,底层共用Docker Host的kernel。
构建镜像

基于CentOS基础镜像构建Java应用镜像

  1. 上传JDK
    创建文件夹,将jdk安装包上传到该目录下
mkdir -p /root/dockerfile/java
  1. 编写dockerfile
    在/root/dockerfile/java目录下创建文件dockerfile_java,内容如下:
FROM centos:7
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk-8u131-linux-x64.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk-8u131-linux-x64.tar.gz \
 && mv ./jdk1.8.0_131 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.ja
  1. 生成镜像
#docker build -f 文件名 -t 镜像名 .代表从当前目录
docker build -f dockerfile_java -t myjava:1.0 
  1. 验证镜像是否生成成功
docker images
  1. 启动容器
docker run --name myjava -d -p 8080:8080 myjava:1.0

通过java镜像构建应用镜像

  1. 编写dockerfile
FROM java:8-alpine
COPY ./docker-demo.jar /tmp/app.jar
# 暴露端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
  1. 生成镜像
#docker build -f 文件名 -t 镜像名 .代表从当前目录
docker build -f dockerfile_java2 -t myjava:2.0 
  1. 验证镜像是否生成成功
docker images
  1. 启动容器
docker run --name myjava2 -d -p 8081:8080 myjava:2.0
  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值