commit命令创建镜像
创建Docker镜像的第一种方法是使用docker commit
命令,可以将此想象为我们往版本控制系统(如Git)中提交变更
我们先创建一个容器,然后在容器里做出修改,最后将修改提交为一个新镜像
创建容器并修改
首先,在一个基础镜像上创建一个容器
sudo docker run -it ubuntu /bin/bash
然后做出修改
apt-get -yqq update
apt-get -y install apache2
最后使用exit
命令退出容器
提交定制容器
先得到刚刚创建的容器的ID
$ sudo docker ps -l -q
4aab3ce3cb76
然后提交修改后的容器
sudo docker commit 4aab3ce3cb76 examples/apache2
也可以在提交镜像时指定更多的数据(包括标签)
sudo docker commit -m"A new custom image" -a"author" 4aab3ce3cb76 example/apache2:webserver
注意docker commit
提交的只是创建容器的镜像与容器的当前状态之间有差异的部分,这使得该更新非常轻量
使用新镜像
检查新创建的镜像
sudo docker images example/apache2:webserver
如果要查看提交的镜像的详细信息
sudo docker inspect example/apache2:webserver
从提交的镜像运行一个新容器
sudo docker run -it example/apache2:webserver /bin/bash
Dockerfile构建镜像
并不推荐使用docker commit
的方法来创建镜像。推荐使用Dockerfile
定义文件和docker build
命令来创建镜像
Dockerfile
使用基本的基于DSL(Domain Specific Language)语法的指令来构建一个Docker镜像
通过Dockerfile
构建镜像更具备可重复性、透明性以及幂等性
创建Dockerfile
首先新建一个目录
mkdir static_web
cd static_web
这个目录就是我们的构建环境(build environment),对于Docker来说,此环境为上下文(context)或者构建上下文(build context)
Docker会在构建镜像时将构建上下文和其中的文件和目录上传到Docker守护进程。这样Docker守护进程就能直接访问用户想在镜像中存储的任何代码、文件或者其他数据
然后新建一个空的Dockerfile
touch Dockerfile
在Dockerfile
文件中写入如下内容
# Version: 0.0.1
FROM ubuntu:14.04
MAINTAINER author "author@axample.com"
RUN apt-get update && apt-get install -y nginx
RUN echo 'I am in your container' \
>/usr/share/nginx/html/index.html
EXPOSE 80
Dockerfile
中的指令可以参照Dockerfile指令
Docker大体上按照如下流程执行Dockerfile
中的指令
- Docker从基础镜像运行一个容器
- 执行一条指令,对容器做出修改
- 执行类似
docker commit
的操作,提交一个新的镜像层 - Docker再基于刚提交的镜像运行一个新容器
- 执行Dockerfile中的下一条指令,直到所有指令都执行完毕
编辑忽略文件
在构建上下文的根目录中新建一个.dockerignore
文件
touch .dockerignore
该文件内容会被按行进行分割,每一行都是一条文件过滤匹配模式。非常像.gitignore
文件,用来设置哪些文件不会被当作构建上下文的一部分,防止它们被上传到Docker守护进程中去,即被忽略。该文件中的匹配规则采用了Go语言中的filepath
执行build命令
在Dockerfile
文件准备好之后,执行构建命令
sudo docker build -t example/static_web:latest .
-t
指令为新镜像设置了仓库名、镜像名和标签,如果没有指定标签,Docker会自动为镜像设置一个latest
标签
上面命令中的.
告诉Docker到当前目录找Dockerfile
文件。
也可以指定一个Git仓库的源地址来指定Dockerfile
的位置,Docker假设这个Git仓库的根目录下存在Dockerfile
文件
sudo docker build -t example/static_web:latest \
git@github.com:example/docker-static_web
使用新镜像
查看新镜像
sudo docker images example/static_web:latest
如果想要深入查看镜像是如何创建出来的
sudo docker history example/static_web:latest
从新镜像启动容器
sudo docker run -d -p 80 --name static-web example/static_web \
nginx -g "daemon off;"
-d
选项告诉Docker以分离(detached)的方式在后台运行
nginx -g "daemon off;"
是需要在容器中运行的命令,这将以前台的运行的方式启动Nginx
-p
标志用来控制Docker在运行时应该公开那些网络端口给宿主机
分配端口
运行一个容器时,Docker可以通过两种方法在宿主机上分配端口
- Docker可以在宿主机上随机选择一个位于32768~61000的一个比较大的端口号来映射到容器中的80端口
- 可以在Docker宿主机中指定一个具体的端口号来映射到容器中的80端口上
先查看一下容器的端口分配情况
sudo docker ps -l
或者
sudo docker port static_web 80
结果假如是
0.0.0.0:49154
-p
选项还可以指定将容器中的端口映射到宿主机的某一端口号上,比如将容器的80端口绑定到宿主机的8080端口
sudo docker run -d -p 8080:80 --name static_web example/static_web \
nginx -g "daemon off;"
也可以将端口绑定到特定的网络接口(IP地址)上,比如将容器的80端口绑定到宿主机的127.0.0.1的80端口上
sudo docker run -d -p 127.0.0.1:80:80 --name static_web example/static_web \
nginx -g "daemon off;"
或者将容器的80端口绑定到宿主机127.0.0.1的随机端口上
sudo docker run -d -p 127.0.0.1::80 --name static_web example/static_web \
nginx -g "daemon off;"
还有一种更简单的方式,使用-P
参数,可以对外公开在Dockerfile
中通过EXPOSE指令公开的所有端口
sudo docker run -d -P --name static_web example/static_web \
nginx -g "daemon off;"
有了映射到宿主机的端口号,就可以连接到运行中的容器
$ curl localhost:49154
I am in your container