3.使用镜像
3.1获取镜像
3.1.1从公共仓库镜像
#格式
docker pull [选项(可省略)] [镜像仓库地址(可省略)] 仓库名/软件名 [:标签(可选,例如版本号)]
#镜像仓库地址格式:(如果没有给出,默认从官方仓库获取)
域名或IP[:端口号(可选)]
#实例
#从官方仓库下载ubuntu 18.04版本
docker pull ubuntu:18.04
查看镜像
docker ps -a
3.1.2运行
有了镜像后,我们可以以镜像为基础启动并运行容器
#指令格式
docker run [可选项] 镜像名称 bash
#可选项
-it:是两个参数 -i表示交互式操作 -t表示终端
-rm:容器推出后随之删除
(默认情况下,推出后容器不会删除,除非使用docker rm)
#bash
执行一些命令并查看返回结果,位于镜像名之后
#例子(运行乌班图镜像)
docker run -it --rm ubuntu:18.04 bash
进入容器后,可以在shell下操作,执行任何所需命令
输入
exit
可以退出容器
3.2 列出镜像
列出已经下载下来的镜像
docker image ls
#显示 仓库名 标签 镜像ID 创建时间 占用空间
3.3删除镜像
删除本地镜像
#指令格式
docker image rm [选项] 镜像ID
#例子 删除乌班图18.04镜像
docker image ls # 查看下载的镜像,找到要删除的乌班图镜像ID
docker image rm 3941d3b032a8
3.4使用commit理解镜像构成
如果是初学者,可以跳过第三章后面内容,直接学习容器
PS:
docker commit主要用于被入侵后保存现场,不要用docker commit定制镜像,定制镜像要用Dockerfile来完成。
镜像是多层存储,每一层是在前一层地基础上进行修改。
容器也是多层存储,是以镜像为基础层,外加一层作为容器运行时的存储层
3.5.1 镜像构建实例
下面以定制一个web服务器为例子,讲解镜像是如何构成的
1.在乌班图虚拟机上,用Nginx镜像启动一个叫做webserver的容器,映射80端口
docker run --name webserver -d -p 80:80 nginx
#在虚拟机浏览器中输入 http://127.0.0.1:80就可访问
2.修改主页面
假设我们想把主页面更换掉,我们可以进入容器,自己写一个主页面,更换为Nginx的index.html
docker exec -it webserver bash
echo '<html> <head><meta charset="utf-8"></head><body> <h1> 欢迎关注 MiaoA知识 <h1> </body </html> ' > /usr/share/nginx/html/index.html
#输入exit
exit
再次输入 http://127.0.0.1:80 显示刚刚被修改的内容
3.查看修改后的容器
我们修改了容器的文件,也就是改动了容器的存储层,可以使用docker diff查看具体改动
#查看
docker diff 容器名
#例子
docker diff webserver
我们运行一个容器时,如果不用卷,我们对容器内文件的任何修改都会记录到容器的存储层中,docker commit命令可以将容器存储层保存下来成为镜像。
用白话说就是:在原来镜像的基础上,加上修改后的存储层,当运行镜像时,就会显示修改后的变化
4.保存修改后的容器为镜像
#格式
docker commit [选项] 容器ID或容器名 [<仓库名>[:<标签>]]
#例子
docker commit \
--author "MiaoA" \
--message "修改了默认网页" \
webserver \
nginx:v2
#解释
--author:指定修改的作者
--message:记录本次修改的备注
5.查看修改后的镜像
#查看新生成的镜像
docker image ls
#查看v2镜像历史记录
docker history nginx:v2
6.运行镜像
#运行刚刚生成的新镜像 我们把端口映射到 外部访问81端口,相当于本地80端口,容器名设置为web2
docker run --name web2 -d -p 81:80 nginx:v2
浏览器输入 127.0.0.1:81,发现其和修改后内容一致
PS
不要用docker commit命令定制容器,因为我们用docker file wedserver时,除了看到index.html被修改外,发现还有一些并不知名文件被修改了,这是docker内部机制决定的,这样会导致镜像极其臃肿。
此外,容器是分层存储的,每一层建立在上一层的基础上,所以每一次修改都会让docker臃肿一次,这对后期维护非常不友好,而且会造成容器越来越臃肿。
所以,再次强调,不要用docker commit 定制容器
3.5利用Dockfile定制镜像
Dockerfile是一个文本文件,包含一条一条指令,每一条指令构建一层(每条指令描述该层如何构建)
下面以定制Nginx为例,使用Dockerfile构建镜像
3.5.1 创建Dockerfile
#创建空白目录
mkdir nginx_test
cd nginx_test
#创建文档
touch Dockerfile
#写入内容
vim Dockerfile
#写入如下
FROM nginx
RUN echo '<html> <head><meta charset="utf-8"></head><body> <h1> 欢迎关注 MiaoA知识 <h1> </body </html> ' > /usr/share/nginx/html/index.html
#解释
FROM 镜像名[:标签] #FROM指定基础镜像,其必须为Dcokerfile中第一条指令
RUN 命令 #在该镜像中执行命令,如果执行多个命令用 &&连接起来 尾部添加 \ 表示换行
3.5.2 构建镜像
利用docker build命令从 Dockerfile 和上下文构建镜像,并且在Dockerfile文件所在目录执行镜像
#格式
docker build [选项] 镜像名[:标签]或者上下文路径或者URL 所执行目录(.表示在当前目录执行)
#例子
docker build -t nginx:v3 .
3.5.3镜像构建上下文
很多初学者会把docker build 命令最后的 . 理解为Dockerfile的路径,这是不准确的。这是在指定上下文路径
上下文介绍
首先介绍docker build原理:
Docker运行时分为Docker引擎(服务端守护进程)和客户端工具,Docker提供了一堆API,用户的命令实际是在客户端通过API与Docker引擎(服务器端守护进程)交互的。(C/S架构)
docker build 是在服务端构建镜像的,与RUN等命令不同(其在客户端构建,所以可以获取本地文件),其应该怎么获取本地文件呢?
答案就是通过上下文,当用docker build构建镜像时,用户会指定镜像上下文路径,docker build命令得知后,会将该路径下所有内容打包,传递给Docker 引擎(服务端),这样就获取本地文件了
#如果在Dockerfile中写
COPY ./package.json /app/
#其表示复制Dockerfile目录下的 package.json到镜像中
#因此,COPY或ADD这些命令中源文件路径都是相对路径,
重点:如果需要复制文件到镜像,必须先把文件复制到上下文目录下,然后上传到镜像中
3.5.4 其他docker build用法
1.直接用Git repo构建
docker build支持从url构建,下面以直接从git repo构建为例
#格式
docker build -t 构建后的镜像名 url(一直到.git结束) #指定分支:指定构建镜像目录
#指定分支为master 构建目录为 /amd64/docker_web 然后docker就会取git clone这个项目,切换到指定分支,进入指定目录后构建
docker build -t docker_web https://gitee.com/gongxusheng/docker-disconf.git#master:amd64/docker_web
2.从标准输入中读取上下文压缩包进行构建
#如果发现输入是以gzip bzip xz结尾的话,会将其当作上下文压缩包,并将其展开,其内容当作上下文,开始构建
docker build - < 生成的压缩包地址(就是以.tar结尾的那个)
3.从标准Dockerfile中构建
docker build - < Dockerfile
更多内容,请关注公众号