前面写过一篇,关于上传镜像到docker hub的文章。docker 创建image上传到 docker hub ,并下载。这篇文章里面的镜像是,是docker pull下来的,是别人镜像。接下来,我们来说说怎么样创建一个完全属于自己的镜像。
1,创建一个文件夹,在该文件夹下创建一个Dockerfile文件
- $ cat Dockerfile
- # Version: 1
- FROM centos:latest
- MAINTAINER tankzhang "***ying@gmail.com"
- RUN yum -y install epel-release
- RUN yum install -y nginx
- RUN echo 'this is test images' > /usr/share/nginx/html/index.html
- CMD ["nginx", "-g", "daemon off;"]
很简单的一个安装nginx并启的一个镜像。关于里面的参数,下面会详细的说到。
2,docker build创建一个镜像
- $ docker build -t tankzhang/centos_nginx:v1 . //注意.表示当前目录
- Sending build context to Docker daemon 2.048 kB
- Step 1/6 : FROM centos:latest
- ---> 8140d0c64310
- 。。。。。。。。。。。。。。。。。。。。。。。。
- Removing intermediate container a075d8c1ffdc
- Successfully built 35a2f6b9e8a3
- Successfully tagged tankzhang/centos_nginx:v1
出现Successfully的字样表示成功,如果不成功的话,用docker images查看,会发现不成功的都是<none>。
3,启动nginx容器
- $ docker run --name mynginx -d -p 8081:80 tankzhang/centos_nginx:v1
- $ docker ps -a |grep mynginx //运行中状态是UP,反之是exited
- 81639bc494f0 tankzhang/centos_nginx:v1 "nginx -g 'daemon off" 22 minutes ago Up 18 minutes 0.0.0.0:8081->80/tcp mynginx
docker命令行的用法非常的多,请参考:docker命令详解
在这里要注意8081是容器外端口,80是容器内端口。这个时候我们就可以通过localhost:8081进行访问了。容器外是没有WEB服务器的,8081端口是被什么程序占用了呢。
- $ netstat -tpnl
- Active Internet connections (only servers)
- Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
- tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1187/sshd
- tcp 0 0 :::22 :::* LISTEN 1187/sshd
- tcp 0 0 :::2376 :::* LISTEN 1237/dockerd
- tcp 0 0 :::8081 :::* LISTEN 20108/docker-proxy
8081被docker-proxy占用了
4,docker hub上面创建远程镜像并且上传
先到https://cloud.docker.com/ 创建一个仓库名为centos_nginx,然后在本地登录,并上传
- $ docker login
- Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
- Username (tankzhang):
- Password:
- Login Succeeded
- $ docker push tankzhang/centos_nginx:v1
- The push refers to a repository [docker.io/tankzhang/centos_nginx]
- 2f1c6546cfa5: Pushed
- a69b66773d0a: Pushing [===============> ] 53.77 MB/175 MB
- 2e2e2c15a2d4: Pushing [===================> ] 35.61 MB/93.1 MB
- b51149973e6a: Pushing [==========> ] 38.59 MB/192.6 MB
到这儿,自己创建的镜像已经传到docker hub了。
下面详细说一下,Dockerfile的参数:
5.
中使用指令
- Dockerfile
5.1
- FROM
指令用于指定其后构建新镜像所使用的基础镜像。
- FROM
指令必是
- FROM
文件中的首条命令,启动构建流程后,Docker将会基于该镜像构建新镜像,
- Dockerfile
后的命令也会基于这个基础镜像。
- FROM
语法格式为:
- FROM
- FROM <image>
或
- FROM <image>:<tag>
或
- FROM <image>:<digest>
通过
指定的镜像,可以是任何有效的基础镜像。
- FROM
有以下限制:
- FROM
必须是
- FROM
中第一条非注释命令
- Dockerfile
文件中创建多个镜像时,
- Dockerfile
可以多次出现。只需在每个新命令
- FROM
之前,记录提交上次的镜像ID。
- FROM
或
- tag
是可选的,如果不使用这两个值时,会使用
- digest
版本的基础镜像
- latest
- RUN
用于在镜像容器中执行命令,其有以下两种命令执行方式:
- RUN
执行
- shell
在这种方式会在
中执行命令,Linux下默认使用
- shell
,Windows下使用
- /bin/sh -c
。
- cmd /S /C
注意:通过
命令修改
- SHELL
所使用的默认
- RUN
- shell
- RUN <command>
执行
- exec
- RUN ["executable", "param1", "param2"]
可以执行任何命令,然后在当前镜像上创建一个新层并提交。提交后的结果镜像将会用在
- RUN
文件的下一步。
- Dockerfile
通过
执行多条命令时,可以通过
- RUN
换行执行:
- \
- RUN /bin/bash -c 'source $HOME/.bashrc; \
- echo $HOME'
也可以在同一行中,通过分号分隔命令:
- RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定
- RUN
参数,如:
- --no-cache
。
- docker build --no-cache
5.3
- CMD
用于指定在容器启动时所要执行的命令。
- CMD
有以下三种格式:
- CMD
- CMD ["executable","param1","param2"]
- CMD ["param1","param2"]
- CMD command param1 param2
不同于
- CMD
,
- RUN
用于指定在容器启动时所要执行的命令,而
- CMD
用于指定镜像构建时所要执行的命令。
- RUN
与
- CMD
在功能实现上也有相似之处。如:
- RUN
- docker run -t -i itbilu/static_web_server /bin/true
等价于:
- cmd ["/bin/true"]
在
- CMD
文件中仅可指定一次,指定多次时,会覆盖前的指令。
- Dockerfile
另外,
命令也会覆盖
- docker run
中
- Dockerfile
命令。如果
- CMD
运行容器时,使用了
- docker run
中
- Dockerfile
相同的命令,就会覆盖
- CMD
中的
- Dockerfile
命令。
- CMD
如,我们在构建镜像的
文件中使用了如下指令:
- Dockerfile
- CMD ["/bin/bash"]
使用
构建一个新镜像,镜像名为
- docker build
。构建完成后,使用这个镜像运行一个新容器,运行效果如下:
- itbilu/test
- $ sudo docker run -i -t itbilu/test
- root@e3597c81aef4:/#
在使用
运行容器时,我们并没有在命令结尾指定会在容器中执行的命令,这时Docker就会执行在
- docker run
的
- Dockerfile
中指定的命令。
- CMD
如果不想使用
中指定的命令,就可以在
- CMD
命令的结尾指定所要运行的命令:
- docker run
- $ sudo docker run -i -t itbilu/test /bin/ps
- PID TTY TIME CMD
- 1 ? 00:00:00 ps
这时,
结尾指定的
- docker run
命令覆盖了
- /bin/ps
的
- Dockerfile
中指定的命令。
- CMD
5.4
- ENTRYPOINT
用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过
- ENTRYPOINT
指定的程序都会被设置为默认程序。
- ENTRYPOINT
有以下两种形式:
- ENTRYPOINT
- ENTRYPOINT ["executable", "param1", "param2"]
- ENTRYPOINT command param1 param2
与
- ENTRYPOINT
非常类似,不同的是通过
- CMD
执行的命令不会覆盖
- docker run
,而
- ENTRYPOINT
命令中指定的任何参数,都会被当做参数再次传递给
- docker run
。
- ENTRYPOINT
中只允许有一个
- Dockerfile
命令,多指定时会覆盖前面的设置,而只执行最后的
- ENTRYPOINT
指令。
- ENTRYPOINT
运行容器时指定的参数都会被传递给
- docker run
,且会覆盖
- ENTRYPOINT
命令指定的参数。如,执行
- CMD
时,
- docker run <image> -d
参数将被传递给入口点。
- -d
也可以通过
重写
- docker run --entrypoint
入口点。
- ENTRYPOINT
如:可以像下面这样指定一个容器执行程序:
- ENTRYPOINT ["/usr/bin/nginx"]
完整构建代码:
- # Version: 0.0.3
- FROM ubuntu:16.04
- MAINTAINER 何民三 "cn.liuht@gmail.com"
- RUN apt-get update
- RUN apt-get install -y nginx
- RUN echo 'Hello World, 我是个容器' \
- > /var/www/html/index.html
- ENTRYPOINT ["/usr/sbin/nginx"]
- EXPOSE 80
使用
构建镜像,并将镜像指定为
- docker build
:
- itbilu/test
- $ sudo docker build -t="itbilu/test" .
构建完成后,使用
启动一个容器:
- itbilu/test
- $ sudo docker run -i -t itbilu/test -g "daemon off;"
在运行容器时,我们使用了
,这个参数将会被传递给
- -g "daemon off;"
,最终在容器中执行的命令为
- ENTRYPOINT
。
- /usr/sbin/nginx -g "daemon off;"
- LABEL
用于为镜像添加元数据,元数以键值对的形式指定:
- LABEL
- LABEL <key>=<value> <key>=<value> <key>=<value> ...
使用
指定元数据时,一条
- LABEL
指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条
- LABEL
指令指定,以免生成过多的中间镜像。
- LABEL
如,通过
指定一些元数据:
- LABEL
- LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
指定后可以通过
查看:
- docker inspect
- $sudo docker inspect itbilu/test
- "Labels": {
- "version": "1.0",
- "description": "这是一个Web服务器",
- "by": "IT笔录"
- },
注意;
中还有个
- Dockerfile
命令,该命令用于指定镜像作者。但
- MAINTAINER
并不推荐使用,更推荐使用
- MAINTAINER
来指定镜像作者。如:
- LABEL
- LABEL maintainer="itbilu.com"
- EXPOSE
用于指定容器在运行时监听的端口:
- EXPOSE
- EXPOSE <port> [<port>...]
并不会让容器的端口访问到主机。要使其可访问,需要在
- EXPOSE
运行容器时通过
- docker run
来发布这些端口,或通过
- -p
参数来发布
- -P
导出的所有端口。
- EXPOSE
- ENV
用于设置环境变量,其有以下两种设置形式:
- ENV
- ENV <key> <value>
- ENV <key>=<value> ...
如,通过
设置一个环境变量:
- ENV
- ENV ITBILU_PATH /home/itbilu/
设置后,这个环境变量在
命令后都可以使用。如:
- ENV
- WORKERDIR $ITBILU_PATH
这些环境变量不仅可以构建镜像过程使用,使用该镜像创建的容器中也可以使用。如:
- $ docker run -i -t itbilu/test
- root@196ca123c0c3:/# cd $ITBILU_PATH
- root@196ca123c0c3:/home/itbilu#
- ADD
用于复制构建环境中的文件或目录到镜像中。其有以下两种使用方式:
- ADD
- ADD <src>... <dest>
- ADD ["<src>",... "<dest>"]
通过
复制文件时,需要通过<src>指定源文件位置,并通过
- ADD
来指定目标位置。<src>可以是一个构建上下文中的文件或目录,也可以是一个
- <dest>
,但不能访问构建上下文之外的文件或目录。
- URL
如,通过
复制一个网络文件:
- ADD
- ADD http://wordpress.org/latest.zip $ITBILU_PATH
在上例中,
是我们使用
- $ITBILU_PATH
指定的一个环境变量。
- ENV
另外,如果使用的是本地归档文件(
、
- gzip
、
- bzip2
)时,Docker会自动进行解包操作,类似使用
- xz
。
- tar -x
- COPY
同样用于复制构建环境中的文件或目录到镜像中。其有以下两种使用方式:
- COPY
- COPY <src>... <dest>
- COPY ["<src>",... "<dest>"]
指令非常类似于
- COPY
,不同点在于
- ADD
只会复制构建目录下的文件,不能使用
- COPY
也不会进行解压操作。
- URL
- VOLUME
用于创建挂载点,即向基于所构建镜像创始的容器添加卷:
- VOLUME
- VOLUME ["/data"]
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。
- VOLUME
如,通过
创建一个挂载点:
- VOLUME
- ENV ITBILU_PATH /home/itbilu/
- VOLUME [$ITBILU_PATH]
构建的镜像,并指定镜像名为
。构建镜像后,使用新构建的运行一个容器。运行容器时,需
- itbilu/test
参将能本地目录绑定到容器的卷(挂载点)上,以使容器可以访问宿主机的数据。
- -v
- $ sudo docker run -i -t -v ~/code/itbilu:/home/itbilu/ itbilu/test
- root@31b0fac536c4:/# cd /home/itbilu/
- root@31b0fac536c4:/home/itbilu# ls
- README.md app.js bin config.js controller db demo document lib minify.js node_modules package.json public routes test views
如上所示,我们已经可以容器的
目录下访问到宿主机
- /home/itbilu/
目录下的数据了。
- ~/code/itbilu
- USER
用于指定运行镜像所使用的用户:
- USER
- USER daemon
使用
指定用户时,可以使用用户名、
- USER
或
- UID
,或是两者的组合。以下都是合法的指定试:
- GID
- USER user
- USER user:group
- USER uid
- USER uid:gid
- USER user:gid
- USER uid:group
使用
指定用户后,
- USER
中其后的命令
- Dockerfile
、
- RUN
、
- CMD
都将使用该用户。镜像构建完成后,通过
- ENTRYPOINT
运行容器时,可以通过
- docker run
参数来覆盖所指定的用户。
- -u
- WORKDIR
用于在容器内设置一个工作目录:
- WORKDIR
- WORKDIR /path/to/workdir
通过
设置工作目录后,
- WORKDIR
中其后的命令
- Dockerfile
、
- RUN
、
- CMD
、
- ENTRYPOINT
、
- ADD
等命令都会在该目录下执行。
- COPY
如,使用
设置工作目录:
- WORKDIR
- WORKDIR /a
- WORKDIR b
- WORKDIR c
- RUN pwd
在以上示例中,
最终将会在
- pwd
目录中执行。
- /a/b/c
在使用
运行容器时,可以通过
- docker run
参数覆盖构建时所设置的工作目录。
- -w
- ARG
用于指定传递给构建运行时的变量:
- ARG
- ARG <name>[=<default value>]
如,通过
指定两个变量:
- ARG
- ARG site
- ARG build_user=IT笔录
以上我们指定了
和
- site
两个变量,其中
- build_user
指定了默认值。在使用
- build_user
构建镜像时,可以通过
- docker build
参数来指定或重设置这些变量的值。
- --build-arg <varname>=<value>
- $ sudo docker build --build-arg site=itiblu.com -t itbilu/test .
这样我们构建了
镜像,其中
- itbilu/test
会被设置为
- site
,由于没有指定
- itbilu.com
,其值将是默认值
- build_user
。
- IT笔录
- ONBUILD
用于设置镜像触发器:
- ONBUILD
- ONBUILD [INSTRUCTION]
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发。
如,当镜像被使用时,可能需要做一些处理:
- [...]
- ONBUILD ADD . /app/src
- ONBUILD RUN /usr/local/bin/python-build --dir /app/src
- [...]
- STOPSIGNAL
用于设置停止容器所要发送的系统调用信号:
- STOPSIGNAL
- STOPSIGNAL signal
所使用的信号必须是内核系统调用表中的合法的值,如:
、
- 9
。
- SIGKILL
- SHELL
用于设置执行命令(
- SHELL
式)所使用的的默认
- shell
类型:
- shell
- SHELL ["executable", "parameters"]
在Windows环境下比较有用,Windows下通常会有
- SHELL
和
- cmd
两种
- powershell
,可能还会有
- shell
。这时就可以通过
- sh
来指定所使用的
- SHELL
类型:
- shell
- FROM microsoft/windowsservercore
- # Executed as cmd /S /C echo default
- RUN echo default
- # Executed as cmd /S /C powershell -command Write-Host default
- RUN powershell -command Write-Host default
- # Executed as powershell -command Write-Host hello
- SHELL ["powershell", "-command"]
- RUN Write-Host hello
- # Executed as cmd /S /C echo hello
- SHELL ["cmd", "/S"", "/C"]
- RUN echo hello
来源: http://blog.51yip.com/cloud/1860.html