四、Docker 的三个基本概念
1.镜像(images):一个特殊的文件系统
操作系统分为内核空间和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)
镜像不包含任何动态数据,其内容在构建之后也不会被改变。
Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。 镜像实际是由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。
比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。
在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。(这点非常类似Git,每次commit都会仅仅修改本次的提交,不会修改之前的commit)
因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
2. 容器:镜像运行时的实体
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的,容器是动态的
容器可以被创建、启动、停止、删除、暂停等
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失(用大白话描述:容器运行过程中存储的数据,在容器停止时就没有了)
按照 Docker官方的建议,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。
所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, 使用数据卷后,容器可以随意删除、重新 run,数据却不会丢失。
3. 仓库:存放镜像文件的地方
仓库:
镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
所以说,仓库是 Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。
Docker Registry 是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
最常使用的 Registry 公开服务是官方的Docker Hub
,这也是默认
的 Registry,并拥有大量的高质量的官方镜像,网址为:hub.docker.com
在国内访问 Docker Hub 可能会比较慢,国内也有一些云服务商提供类似于 Docker Hub 的公开服务。
除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。
开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 Docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。
版本:
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本
我们可以通过<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest
作为默认标签。
4. 一句话总结
镜像:已经打包好的 Docker 应用,有点类似于一个程序的安装包。
镜像仓库:存储镜像的服务器
容器:有了镜像我们就可以创建容器了,容器就是运行着的镜像,一个镜像可以同时创建多个容器,容器之间的隔离的。
Download Docker Desktop | Docker
Linux 用户配置加速器
针对安装了 Docker 的 Linux 用户,您可以参考以下配置步骤:
修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
对于使用 Windows 10
的用户,在任务栏托盘 Docker 图标内右键菜单选择 Settings
,打开配置窗口后在左侧导航菜单选择 Docker Engine
,在右侧像下边一样编辑 json 文件,之后点击 Apply & Restart
保存后 Docker 就会重启并应用配置的镜像地址了。
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
1. 打开终端
2. 输入命令
docker run hello-world
docker run -it ubuntu bash
-it:交互模式:在窗口中运行Ubuntu这个容器,运行bash软件
一个容器适合运行单一程序
一、运行终端
打开终端,输入docker images ,如果运行正常,表示docker已经可以在本电脑上使用了
image-20191118102525668
二、docker常用命令
指令 | 说明 |
---|---|
docker images | 查看已下载的镜像 |
docker rmi 镜像id | 删除已下载的镜像 rm 镜像名称:标签名 |
docker search 镜像 | 从官方仓库(hub.docker.com)查找镜像 |
docker pull 镜像名称:标签名 | 标签名默认是 latest,代表最新版本。 |
docker run | 创建容器 |
docker ps | 列出运行中的容器(运行中)process status |
docker ps -a | 列出所有的容器(运行、未运行) |
docker rm 容器名称 | 删除停止的容器 |
docker rm -f 容器名称 | 删除运行中的容器 |
docker start 容器名称 | 启动容器 |
docker stop 容器名称 | 停止容器 |
docker restart 容器名称 | 重启容器 |
docker exec | 执行容器中的指令 |
如果在使用过程中有疑惑的地方,可以使用帮助文档查看
1. 拉取MySql镜像
docker pull mysql:5.5
下载完成后,我们就可以在本地镜像列表里看到名为 mysql ,标签为5.5的镜像
2. 使用MySql镜像
运行容器
docker run -d --name=mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.5
命令说明:
--name=mysql:为容器指定一个名称为mysql
-p 3306:3306:将容器的(后面的3306) 3306 端口映射到主机的(前面的3306) 3306端口。
-d:后台运行容器,并返回容器ID。
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码为123456。
mysql:5.5 要使用的镜像的名称
注意:
如果本地已经使用了3306端口,那么可以容器的3306端口映射到本机端口的3307或者其他的
docker run -d --name=mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.5
运行效果:
3. 连接数据库
docker run -it -p 12345:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.5
虚拟机输入 ipconfig,第一个 IPv4 地址 是本地虚拟机的ip地址
192.168.50.129
4.1 Docker pull 命令
docker pull : 从镜像仓库中拉取或者更新指定镜像
语法
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
OPTIONS说明:
-a :拉取所有 tagged 镜像
实例
从Docker Hub下载MySql 8.0.1版镜像
docker pull mysql:8.0.1
从Docker Hub下载REPOSITORY为mysql的所有版本的镜像
docker pull -a mysql
4.2 Docker images 命令
docker images : 列出本地镜像
语法
docker images [OPTIONS] [REPOSITORY[:TAG]]
OPTIONS说明:
实例
4.3 Docker tag 命令
docker tag : 标记本地镜像,将其归入某一仓库
语法
docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
实例
将镜像registry.cn-hangzhou.aliyuncs.com/xavier/laravel
标记为test/laravel:latest
镜像
docker tag registry.cn-hangzhou.aliyuncs.com/xavier/laravel test/laravel
docker images laravel
4.4 Docker rmi 命令
docker rmi : 删除本地一个或多个镜像
语法
docker rmi [OPTIONS] IMAGE [IMAGE...]
OPTIONS说明:
什么是过程镜像:在构建新镜像的过程中产生的镜像或者依赖的镜像
实例
强制删除本地镜像mysql:5.5
docker rmi -f mysql:5.5 mysql:5.6
什么时候需要用强制删除呢?在你普通删除删不掉的时候
4.5 Docker run 命令
docker run :创建一个新的容器并运行一个命令
语法
docker run --name 容器名称 -d -p 主机端口:容器内端口 -e 环境变量 --link 其它容器名:容器中别名 镜像名称:标签名
实例
使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为wuxidixi。且映射容器80端口到主机8000端口
docker run --name=wuxidixi -d -p 80:80 nginx:latest
4.6 Docker start/stop/restart 命令
docker start :启动一个或多少已经被停止的容器
docker stop :停止一个运行中的容器
docker restart :重启容器
语法
docker start CONTAINER
docker stop CONTAINER
docker restart CONTAINER
实例
停止运行中的容器
docker stop 容器id
启动已被停止的容器mysql
docker start 容器id
重启容器yigubigu
docker restart 容器id
docker ps -a 所有容器
docker start 容器id
docker start -i 容器id (以交互模式运行)
4.7 Docker rm 命令
docker rm :删除一个或多个容器
语法
docker rm [OPTIONS] CONTAINER [CONTAINER...]
OPTIONS说明:
实例
s强制删除容器mysql
docker rm -f mysql
移除容器yigubigu对容器mysql的连接,连接名mysql
docker rm -l mysql
删除多个容器时,用空格隔开
删除容器nginx01,并删除容器挂载的数据卷
docker rm -v nginx01
docker ps // 查看所有正在运行容器
docker stop containerId // containerId 是容器的ID
docker ps -a // 查看所有容器
docker ps -a -q // 查看所有容器ID
docker stop $(docker ps -a -q) // stop停止所有容器
docker rm $(docker ps -a -q) 删除所有停止的容器
docker rm $(docker ps -a -q) // remove删除所有容器
docker exec :运行一个容器,并运行这个容器其他命令
Docker exec命令用于在运行的Docker容器中执行命令。以下是一些常见的使用例子:
运行bash shell:
docker exec -it container_id /bin/bash
这个命令会在指定的容器中启动一个新的bash shell,允许你在容器内部进行交互操作。
查看容器中的环境变量:
docker exec container_id env
这个命令会列出在容器中定义的所有环境变。
查看容器中的文件:
docker exec container_id ls /path/to/directory
这个命令会列出容器中指定目录下的所有文件。
在容器中运行一个Python脚本:
docker exec container_id python /path/to/script.py
这个命令会在容器中运行指定的Python脚本。
在容器中安装软件:
docker exec container_id apt-get install -y package_name
这个命令会在容器中安装指定的软件包。
注意:在使用docker exec命令时,你需要确保目标容器正在运行。如果容器没有运行,你可以使用docker start命令来启动它。
docker images----->查看本地所有的镜像
docker run镜像名字:版本 ---->创建一个容器且运行
-it--->交互模式
docker run -it 镜像名字:版本 ---->创建一个容器且运行默认的启动的程序
docker run -it 镜像名字:版本 [命令] ---->创建一个容器且运行的是[命令]命令程序,而不是默认启动的程序
docker run-it ubuntu bash --->创建一个容器且运行bash而不是默认启动的程序,注意bash是Ubuntu镜像中自带的而不是docker的
docker pull 镜像名字:版本 ---->下载一个镜像
docker pull 镜像名 ---->下载最新版
docker ps 查看正在运行的容器
docker ps -a 查看所有的容器
docker stop 容器的id ---->停止一个容器的运行(并没有删除,仅仅是停止运行)
docker start 容器的id ---->将一个已经停止运行的容器再次运行起来
docker start -i 容器的id ---->在将一个停止的容器运行起来的同时,指定交互模式
docker rm 容器的id ---->删除已经停止运行的容器
docker rm $(docker ps -a -q) --->删除所有停止运行的容器(慎用)
docker rm -f 容器的id ---->强制删除容器(无论是否停止运行)
docker rmi 镜像的id --->删除镜像的id(注意,如果这个镜像被被的容器正在使用包括停止运行的容器,那么此时先删除容器,再删除镜像)
docker search 名字 ---->搜索匹配的镜像(https://hub.docker.com)中搜索
docker exec 容器的id 容器中的命令(存在的程序) ---->能够让正在运行中的容器,可以运行一个新的程序(命令)
docker run -d --name=mysql -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.5
解释:
-d :后台运行,什么也看不见
--name : 给容器设置名字(如果重复的话就失败)
-p xxx:yyy xxx是操作系统的端口 yyy是容器中用到的端口,作用是:将本机的XXX端口与容器中的yyy端口做映射
-e :environment的意思,就是给容器设置环境变量。用它可以将参数传递给容器
redis图形化工具 AnotherRedisDesktopManager
GitHub - qishibo/AnotherRedisDesktopManager:
安装redis:
docker run -d --name redis-test -p 6379:6379 redis
安装MongoDB
docker run --name mongo-test -d -p 27017:27017 mongo
通过Docker安装MongoDB - 墨天轮
问题一
数据是保存在容器里的,如果容器删除了数据也就删除了
问题二
每次要修改容器时,必须要进入到容器中去修改,比如要修改my.cnf
为了能够保存(持久化)数据以及共享容器间的数据,Docker 提出了 Volume 的概念
可以使用 -v 这个参数,将容器中的一个目录或者文件 和主机上的目录和文件进行绑定,绑定之后,修改主机上的这个文件就相当于修改了容器中的文件,删除容器之后,绑定的目录和文件还在主机(不会被删除)
为了实现主机和容器之间的数据共享,我们可以在创建容器时添加 -v 参数:
docker run ... -v 主机目录:容器中的目录 ...
demo1
1.创建一个新容器,且设置共享路径
注意:创建时镜像名字放在最后
image-20191118145724861
2.真实电脑创建文件、文件夹,容器看到共享成功 image-20191118145907498
3.容器修改文件内容,真实电脑看到共享数据成功 image-20191118150045558
demo2
目的:重启docker容器看数据能否再次使用
1.退出容器
image-20191118150252608
2.修改真实电脑文件数据 image-20191118150310750
3.再次运行容器 image-20191118150402536
4.查看容器是否看到共享数据,结果成功 image-20191118150450264
demo3
目的:删除容器之后共享文件(夹)是否会丢失
1.退出、删除容器
image-20191118150653079
2.查看真实电脑文件依然在 image-20191118150711531
我们可以使用 docker cp 指令向容器中复制文件,或者从容器中复制文件到主机
docker cp 源目录 目标目录
1.创建一个新的容器
image-20191118151011166
2.查看真实电脑路径下无文件(夹)
image-201911181511116533.从容器复制文件到真实电脑
image-20191118151226228
4.从真正电脑复制文件夹到容器
有时,我们在一个容器中安装了需要的软件或者进行了较为复杂的配置,此时能否把这个容器制作成一个镜像呢?
答案:可以
这样我们就可以将这个镜像进行分享,从而让其他的开发者也直接可以使用
基本的镜像->容器->在这个容器中安装你需要的软件->通过手段做成一个新镜像->传到仓库->别人可以从仓库中下载这个新的镜像->可以创建容器
1.下载一个需要的基本镜像
docker pull ubuntu:16.04
2.创建一个容器
docker run -it ubuntu:16.04
3,在容器中安装、配置满足你的需求
如果想要安装vi(编辑器),那么就得需要apt install vi,想要用apt
install 快速的安装软件的话,那么就得需要修改/etc/apt/sources.List文件
那么怎么改这个文件呢?
查看sources.list文件:cat /etc/apt/sources.list
3.1 在自己的电脑上编辑一个文件sources.list,然后写入新的更新源地址
3.2 通过docker cp sources.list 容器id:/home 将sources.List复制到容器中
3.3 在容器中将/home下的sources.List替换到/etc/apt下的sources.list文件
cd /home
cp sources.list /etc/apt/
3.4让更新源生效apt update
3.5安装vim
apt install vim
vim /etc/apt/sources.list
我们可以直接使用 docker commit 指令将一个容器制作成一个镜像:
docker commit 容器名称 镜像名称:标签
docker commit -m "更新源清华,安装了vim编辑器" 40ffe8201 ubuntu_gai:1.0
4.将容器打包为镜像
docker commit-m"备注"容器的id镜像的名字:版本
5.上传
5.1先在https://hub.docker.com注册&登录
5.2在终端中docker login登录
5.3通过tag打标签
docker tag 镜像名:版本用户名/镜像名:版本
5.4推送到仓库
docker push用户名/镜像名:版本
制作好镜像之后,我们就可以把镜像上传到 docker 的仓库中
docker 的官方网站为注册用户提供了一个 docker 仓库,我们可以把我们自己的镜像放到 docker 官方的仓库上
一、注册账号
首先需要到 docker 官方网站上注册一个账号(如果注册不了,那么请自行百度科学上网)
二、登录
注册成功之后就可以登录,登录之后可以进入自己的仓库中
三、上传镜像
先在本地登录
执行以下指令进行登录(需要输入账号、密码)也可以用token登录:
docker login
打标签
登录成功之后,还需要为要上传的镜像打一个标签,注意这个标签必须要以 账号/ 开头:
docker tag 本地镜像:标签 账号/镜像名称:标签
比如,我的账号是 dong4716138 ,现在我要将本地的my_nginx:1.0上传到仓库中,那么首先我们对这个镜像打标签:
docker tag my_nginx:1.0 dong4716138/my_nginx:1.0
docker tag ubuntu_gai:1.0 qcbaskqenynotj/ubuntu_gai:1.0
上传
打完标签之后,我们就可以上传了:
docker push 账号/镜像:标签
docker push qcbaskqenynotj/ubuntu_gai:1.0
如:
docker push dong4716138/my_nginx:1.0
这个指令会将镜像上传到 my_nginx 这个仓库中
搜索是否可以下载指定版本的镜像
1.找一个新的文件夹(这样的目的是:保证这个文件夹中是空的,如果不是空文件夹,那么在构建新的镜像时,会将这些没用的文件也上传打包到docker引擎中用)
2.创建一个新的文件Dockerfile
3.编辑Dockerfile文件
#检查本地是否有nginx:latest版本,如果有则创建容器,如果没有则先下载
FROM nginx
#在这个容器中运行-次命令,echo,.,是将index,html文件进行修改为
一、引入
从刚才的 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。
这个脚本就是 Dockerfile
二、什么是Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的 **指令(Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
下载nginx镜像
docker pull nignx
创建容器
docker run --rm -p 8002:80 nginx
说明:
--rm的作用是,当这个容器退出时,自动删除这个容器
使用浏览器访问8002端口 127.0.0.1:8002
四、使用Dockerfile
在一个空白目录中,建立一个文本文件,并命名为 Dockerfile:
$ mkdir my_nginx
$ cd my_nginx
$ touch Dockerfile
修改Dockerfile内容如下:
FROM nginx
RUN echo 'Hello, Docker!
' > /usr/share/nginx/html/index.html
#检查本地是否有nginx:latest版本,如果有则创建容器,如果没有则先下载
FROM nginx
#在这个容器中运行-一次命令,echo..,是将index.html文件进行修改为Hello,Docker!
RUN echo 'Hello,Docker!
'>/usr/share/nginx/html/index.html
#当上述的RUN命令执行完之后,docker会立刻进行打包为一个镜像(层)
> 覆盖 >>追加
docker run --rm -it -p 8002:80 nginx bash
echo 'Hello, Docker!
' > /usr/share/nginx/html/index.html
打开 127.0.0.1:8002
检查镜像的信息
docker inspect 镜像的名字:版本
Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile
中的指令自动生成映像。
docker build
命令用于从Dockerfile构建映像。可以在docker build
命令中使用-f
标志指向文件系统中任何位置的Dockerfile。
例:
docker build -f /path/to/a/Dockerfile
Dockerfile的基本结构
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。
Dockerfile文件说明
Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#
字符开头则被视为注释。可以在Docker文件中使用RUN
,CMD
,FROM
,EXPOSE
,ENV
等指令。
在这里列出了一些常用的指令。
FROM:指定基础镜像,必须为第一个命令
格式:
FROM
FROM :
FROM @
示例:
FROM mysql:5.6
注:
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
MAINTAINER: 维护者信息
格式:
MAINTAINER
示例:
MAINTAINER xxxxx
MAINTAINER [email protected]
MAINTAINER xxxxxx
RUN:构建镜像时执行的命令
RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
RUN
exec执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
注:
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
格式:
ADD ...
ADD ["",... ""] 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
CMD:构建容器后调用,也就是在容器启动时才进行调用。
格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
示例:
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
注:
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
ENV:设置环境变量
格式:
ENV #之后的所有内容均会被视为其的组成部分,因此,一次只能设置一个变量
ENV = ... #可以设置多个变量,每个变量为一个"="的键值对,如果中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
EXPOSE:指定于外界交互的端口
格式:
EXPOSE [...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注:
EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
VOLUME:用于指定持久化目录
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
注:
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它
WORKDIR:工作目录,类似于cd命令
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
**USER:**指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
格式:
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
示例:
USER www
注:
使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run
运行容器时,可以通过-u参数来覆盖所指定的用户。
ARG:用于指定传递给构建运行时的变量
格式:
ARG [=]
示例:
ARG site
ARG build_user=www
以下是一个小例子:
# Base images 基础镜像
FROM centos
#MAINTAINER 维护者信息
MAINTAINER xxxxxx
#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
#ADD 文件放在当前目录下,拷过去会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/
#RUN 执行以下命令
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www
#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install
RUN echo "daemon off;" >> /etc/nginx.conf
#EXPOSE 映射端口
EXPOSE 80
#CMD 运行以下命令
CMD ["nginx"]
最后用一张图解释常用指令的意义^-^
1.新建sources.list
文件内容如下:
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal universe
deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe
deb http://mirrors.aliyun.com/ubuntu/ focal multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-security universe
deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse
Dockerfile
文件内容如下:
FROM ubuntu:20.04
COPY sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install vim -y
运行命令:
docker build -t ubuntu_flask:1.0 .
2. 安装Python3(ubuntu_flask:1.1)
Dockerfile_1.1文件内容如下:(从之前建立好的镜像,基础之上安装python3)
FROM ubuntu_flask:1.0
RUN apt-get install python3 -y
运行命令:(-f 指定Dockerfile是谁)
docker build -t ubuntu_flask:1.1 . -f Dockerfile_1.1
3. 安装pip3(ubuntu_flask:1.2)、安装flask需要的模块、包(ubuntu_flask:1.3)
开始构建
requirements.txt
内容如下:(如果大家之前已经养成了用python虚拟换的好习惯,此时只需要切换虚拟环境然后pip freeze > requirements.txt就可以得到此文件,所以再次建议要用Python的虚拟环境)(> 覆盖)
click==8.1.3
colorama==0.4.6
Flask==2.2.3
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
Werkzeug==2.2.3
Dockerfile1.2
内容如下:
FROM ubuntu_flask:1.1
RUN apt-get install python3-pip -y
# 复制文件到容器
ADD requirements.txt /home
# 跳转到指定目录
WORKDIR /home
RUN pip3 install -r requirements.txt -i https://pypi.mirrors.ustc.edu.cn/simple/
命令:
docker build -t ubuntu_flask:1.2 . -f Dockerfile1.2
5. 编写测试flask项目(ubuntu_flask:1.3)
main.py
内容如下:
from flask import Flask
# 创建flask对象
app = Flask(__name__)
a=1
@app.route('/')
def index():
"""
处理一个页面的逻辑
:return:
"""
return f'hello flask {a}'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8899, debug=True) # 如果是127.0.0.1那么意味着只能容器本身能访问,其他电脑不行
Dockerfile1.3
内容如下:
FROM ubuntu_flask:1.2
# 进入到项目目录
WORKDIR /home
# 拷贝flask示例.py到工作目录(此时的.就是/home路径的意思,因为上面已经使用WORKDIR设置了)
COPY main.py .
# 对外暴露端口
EXPOSE 8899
# 运行测试项目
CMD ["python3","main.py"]
命令如下:
docker build -t ubuntu_flask:1.3 . -f Dockerfile1.3
6. 运行 & 测试
docker run --rm -it -p 8899:8899 ubuntu_flask:1.3
效果如下:
切换到Ubuntu20.04终于成功了
1. 目的
上一节中已经完成了flask开发环境操作,但是发现有了很多次的Dockerfile才完成,这是很麻烦的,为了更加方便的操作使用,我们本小节将对上一节的之后进行升级为一个Dockerfile
2. 实现
将基础班中的5个Dockerfile文件合并为一个,名字叫做Dockerfile_2.0 适当修改后如下:
FROM ubuntu:20.04
# 复制国内更新源
COPY sources.list /etc/apt/sources.list
# 跳转到指定目录
WORKDIR /home
# 复制文件到容器
COPY requirements.txt .
# 安装vim、python3、pip3以及flask用的包
RUN apt-get update && apt-get install vim -y \
&& apt-get install python3 -y \
&& apt-get install python3-pip -y \
&& pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制flask示例py文件
COPY main.py .
# 对外暴露端口
EXPOSE 8899
# 运行测试项目
CMD ["python3","main.py"]
命令:
docker build -t ubuntu_flask:2.0 . -f Dockerfile_2.0
1.检查虚拟机-设置-处理器-虚拟化引擎
勾选前两项
2、再次启动Docker以后,如果卡在starting界面1.
点击TroubleShoot
分别尝试这两个选项,点完后,发现出现了新的状态:Docker Desktop is Stopping.....
卸载Docker Desktop,重新安装,突然发现可以正常使用了
解决Docker 一直starting 的办法_普通网友的博客-CSDN博客_docker desktop starting...