1. Dockerfile
- Dockerfile
Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile快速创建自定义的镜像。
Dockerfile由一行行命令语句组成,基本一行命令就代表镜像封装中的一层,其中每一条指令都创建镜像的一层。
Dockerfile一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。- 其指令的具体信息如下:
- FROM
格式为FROM < image > 或FROM< image >:< tag >。
第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一一次)。- MAINTAINER
格式为MAINTAINER < name >, 指定维护者信息。- RUN
格式为RUN < command > 或RUN [ “executable”, “param1”, “param2”]。
前者将在shell终端中运行命令,即/bin/sh -C ;后者则使用exec执行。指定使用其他终端可以通过第二种方式实现,例如RUN[“/bin/bash”,”-C”,”echohello”]。每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\来换行。- CMD
支持三种格式:
CMD [“executable”, “param1”, “param2”]使用exec执行,推荐方式。
CMD command param1 param2 在/bin/sh中执行,提供给需要交互的应用。
CMD [“param1”, “param2”]提供给ENTRYPOINT的默认参数。
指定启动容器时执行的命令,每个Dockerfile只能有一-条CMD命令。如果指定了多条
命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉CMD指定的命令。- EXPOSE
格式为EXPOSE < port > [< port >…]。
例如:EXPOSE 22 80 8443
告诉Docker服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过-P,Docker主机会自动分配一个端口转发到指定的端口;使用-P,则可以具体指定哪个本地端口映射过来。- COPY
格式为COPY < src > < dest >。
复制本地主机的< src > (为Dockerfile所在目录的相对路径,文件或目录)为容器中的< dest >。目标路径不存在时,会自动创建。
当使用本地目录为源目录时,推荐使用COPY。- ENTRYPOINT
有两种格式:
ENTRYPOINT [ “executable”, “param1”, “param2”]
ENTRYPOINT command param1 param2 ( shell中执行)。
配置容器启动后执行的命令,并且不可被docker run 提供的参数覆盖。
每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT时,只有最后一个生效。- VOLUME
格式为VOLUME [“/data”]。
创建-一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
1. 简单的dockerfile示例,建立一个封装httpd服务的镜像
進行httpd 服務的鏡像封裝:
編輯Dockerfile:
vim Dockerfile
FROM rhel7 # 父镜像
ENV HOSTNAME test1
MAINTAINER root@localhost
EXPOSE 80 # 服务端口号
COPY yum.repo /etc/yum.repos.d/yum.repo # yum 源文件,需要进行指定
RUN rpm --rebuilddb && yum install -y httpd && yum clean all
VOLUME ["/var/www/html"]
# run 命令,进行httpd服务的安装
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
# 用镜像创建实例后,最终执行的命令
可能会遇到以下问题:
rpm数据库损坏需要重建。因此需要在 “yum install …” 前使用 “rpm –rebuilddb” 重建数据库。比如:
RUN rpm –rebuilddb && yum install -y sudo …
在我的环境中发现有时候如果有多条 “RUN yum install -y …” 指令,需要在每条之前都加上 “rpm –rebuilddb”。
创建镜像
编写完成Dockerfile之后,可以通过docker build 命令来创建镜像。
基本的格式为docker build[ 选项]路径,该命令将读取指定路径下(包括子目录)的 Dockefile,并将该路径下所有内容发送给Docker服务端,由服务端来创建镜像。因此一般建议 放置Dockerfile 的目录为空目录。
执行如下:
docker built -t rhel7:httpd /tmp/docker/Dockerfile/httpd
2. 一个镜像封装多个服务
这里会用到supervisord
- supervisord是一个进程管理工具,能对进程进行自动重启等操作。
优点:
- 可以将非后台运行程序后台运行
- 自动监控,重启进程
缺点:- 不能管理后台运行程序
- 对多进程服务,不能使用kill关闭
编辑 supervisord 文件
1 [surpervisord]
2 nodaemon=true
3
4 [program:sshd]
5 command=/usr/sbin/sshd -D # 启动sshd服务
6
7 [program:httpd]
8 command=/usr/sbin/httpd # 启动httpd服务
Dockerifle
1 FROM rhel7
2 EXPOSE 80 22 # 一次暴露多个端口
3 COPY yum.repo /etc/yum.repos.d/yum.repo
4 RUN rpm --rebuilddb && yum install -y httpd && yum clean all && rpm --rebuil ddb && yum install -y openssh-server openssh-clients supervisor && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:redhat | chpasswd
5 COPY supervisord.conf /etc/supervisord.conf
6 CMD ["/usr/bin/supervisord"] # 通过 supervisord 来进行
然后进行镜像生成
docker build -t rhel7:mutil /tmp/docker/dockerfile/mutil
2. 仓库
- 仓库(Repository)是集中存放镜像的地方。
每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 dl.dockerpool.com/ubuntu 来说, dl.dockerpool.com 是注册服务器地址,,ubuntu 是仓库名。
大部分时候,并不需要严格区分这两者的概念。
目前 Docker 官方维护了一个公共仓库 Docker Hub (https://hub.docker.com/) ,其中已经包括了超过 15,000 的镜像。大部分需求,都可以通过在 Docker Hub 中直接下载镜像来实现。
我这里着重强调进行用户私有仓库的创建- 使用registry镜像创建私有仓库
安装Docker后,可以通过官方提供的registry镜像来简单搭建一套本地私有仓库环境:
docker run -d -P 5000:5000 registry
这将自动下载并启动一个registry容器,创建本地的私有仓库服务。
默认情况下,会将仓库创建在容器的/tmp/registry目录下。可以通过-V参数来将镜像文件存放在本地的指定路径上。
示例如下:
1. 简单的本地免密仓库
# 在本地启动一个私有仓库服务,监听端口为5000
[root@foundation25 821]# docker run -d -p 5000:5000 -v /opt/registry:/var/lib/registry registry
2d25eda8bc70f36ed240fb8f87009d18020b19ad9e94712fcf4758b38d0d0470
[root@foundation25 821]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d25eda8bc70 registry "docker-registry" 3 seconds ago Up 1 second 0.0.0.0:5000->5000/tcp dreamy_noyce
# 建立要推送到本地仓库的镜像
[root@foundation25 821]# docker tag ubuntu localhost:5000/ubuntu
# 使用docer push 上传标记镜像
[root@foundation25 821]# docker push localhost:5000/ubuntu
The push refers to a repository [localhost:5000/ubuntu]
5f70bf18a086: Image successfully pushed
11083b444c90: Image successfully pushed
9468150a390c: Image successfully pushed
56abdd66ba31: Image successfully pushed
Pushing tag for rev [07c86167cdc4] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}
# 删除本地已有的ubuntu镜像
[root@foundation25 821]# docker rmi -f localhost:5000/ubuntu ubuntu
# 从本地仓库拉取上传过的镜像:localhost:5000/ubuntu
[root@foundation25 821]# docker pull localhost:5000/ubuntu
以上是简单的本机仓库的搭建,但是除了本地用户外别的用户无法应用,这明显是很不方便的,我们可以搭建一个主机外用户可以访问的仓库,以适应生产需求
2. 配置用户免费HTTPS证书仓库
建立目录,进行证书的获取
# 建立指定目录
[root@foundation25 ~]# mkdir /etc/docker/certs
[root@foundation25 ~]# cd /etc/docker/
# 进入指定目录的上一级,并进行证书及密钥的获取
[root@foundation25 docker]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
Generating a 4096 bit RSA private key
.................................................................................................................................................................................................++
......++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shaanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:test
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:test.com
Email Address []:root@localhost
# 获取成功
[root@foundation25 docker]# ls certs/
domain.crt domain.key
[root@foundation25 docker]# pwd
/etc/docker
# 将密钥移动到指定位置(/etc/docker/certs.d/'domain'/ca.crt)
# 注意要添加好本地域名解析
[root@foundation25 docker]# mkdir /etc/docker/certs.d/test.com -p
[root@foundation25 docker]# cp /etc/docker/certs/domain.crt /etc/docker/certs.d/test.com/ca.crt
[root@foundation25 docker]# ls /etc/docker/certs.d/test.com/ca.crt
/etc/docker/certs.d/test.com/ca.crt
# 启动一个registry容器
[root@foundation25 docker]# docker run -d \
> --restart=always \
> --name registry \
> -v `pwd`/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
> -p 443:443 \
> registry
9bcc3ee45b386014f1480e076fdc330a71a85849eb10ac2404c611ab057f9954
[root@foundation25 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9bcc3ee45b38 registry "docker-registry" 8 seconds ago Up 7 seconds 0.0.0.0:443->443/tcp, 5000/tcp registry
然后进行本地镜像的上传:
[root@foundation25 docker]# docker push test.com/rhel7
3. 配置加密仓库
清除上个实验的容器,但是保留建立的证书与密钥
[root@foundation25 docker]# docker run -d --restart=always \
> --name registry -v `pwd`/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -v `pwd`/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> -p 443:443 \
> 83139345d017 # 镜像 ID
3539268d9f8af52b1f66ed443e518570674bb8ccb5c44866e6474ef469f01607
# 启动仓库服务后,查看容器列表
[root@foundation21 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3539268d9f8a 83139345d017 "/bin/registry /et..." 5 seconds ago Up 4 seconds 0.0.0.0:443->443/tcp, 5000/tcp registry
进行镜像的上传,被拒绝,因为没有进行认证
[root@foundation21 docker]# docker push test.com/nginx
The push refers to a repository [test.com/nginx]
18af9eb19b5f: Preparing
no basic auth credentials
登录仓库后,再进行上传
# 进行用户登陆
[root@foundation25 docker]# docker login -u test -p redhat test.com
Login Succeeded
# 上传镜像
[root@foundation25 docker]# docker push test.com/nginx
The push refers to a repository [test.com/nginx]
18af9eb19b5f: Pushed
latest: digest: sha256:f1b19bc905965d1ff157c76b9ef6615c119aadad3cf4652bc881d3354ba3fdc4 size: 528