目录
11.配置systemctl下管理docker及更改镜像和容器的默认位置... 7
11.6更改容器和镜像的默认存储位置/var/lib/docker 11
12 docker的daemon.json的配置参数... 11
13或更改docker的镜像和容器的默认存储位置... 13
2 安装harbor-offline-installer-v1.5.1.tgz. 18
4) 修改 Harbor 的配置文件 hardor.cfg. 32
1.下载docker安装包
即docker-17.05.0-ce.tgz
下载地址 https://github.com/moby/moby/releases
17.05.0下载 :
https://get.docker.com/builds/Linux/x86_64/ docker-17.05.0-ce.tgz
或
curl https://get.daocloud.io/docker/builds/Linux/x86_64/docker-17.05.0-ce.tgz
2.上传到服务器中安装
3.解压安装包
tar -zxvf docker-17.05.0-ce.tgz
4.移动文件
即将解压的目录下的所有文件移动到/usr/bin/或/usr/local/bin/下面
mv docker/ * /usr/bin/
5.切换到root用户
在执行操作mv docker/ * /usr/local/bin/(自定义但必须是bin下)
6.查看docker --version
7.Docker info出现
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
解决:
进入bin目录
cd /usr/local/bin (对于docker的所有操作都要在该目录下)
启动docker的守护进行:
./dockerd &
现在在docker info
在解决没有docker组及进程问题
8.查看docker进程
现在docker安装成功,命令可用
9.配置docker的工作路径(可选)
(可以在任何目录下对docker进行操作)
vi /etc/profile
在文件最后添加:
export DOCKER_HOME=/usr/local/bin(docker安装目录)
export PATH=.:$DOCKER_HOME:$PATH
执行:
source /etc/profile
10.用env查看环境变量
docker二进制安装就成功
11.配置systemctl下管理docker及更改镜像和容器的默认位置
11.1 配置docker文件
在/etc/default/下创建docker文件touch /etc/default/docker
编辑文件
[yan@bogon ~]$ vim /etc/default/docker
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com --insecure-registry=192.168.19.128:5000 --graph=/data/gdeop/docker --storage-driver=overlay "
或
DOCKER_OPTS="-H unix:///var/run/docker.sock -H 0.0.0.0:5555 --graph=/data/gdeop/docker --storage-driver=overlay"
11.2 docker.server的配置
创建docker.server文件,编辑
[yan@bogon ~]$ vim /etc/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
Requires=docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/docker daemon -H fd:// $DOCKER_OPTS
EnvironmentFile=-/etc/default/docker
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
#StartLimitBurst=20
#StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
11.3 docker.socket的配置
创建docker.socket文件,编辑
[yan@bogon ~]$ vim /etc/systemd/system/docker.socket
[Unit]
Description=Docker Socket for the API
PartOf=docker.service
[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
11.4创建docker用户组
groupadd docker
11.5加入用户组
usermod -aG docker gdeop
注:gdeop是用户名
11.6更改容器和镜像的默认存储位置/var/lib/docker(11.1或)
11.6.1首先用systemctl stop docker
在用rsync -avz /var/lib/docker 命令
例如:rsync -avz /var/lib/docker /data/gdeop/
在进行加载systemctl daemon-reload
12 docker的daemon.json的配置参数
注:docker1.13的版本以上有效,默认位置是/etc/docker/ 二进制安装docker中daemon.json是没有的,如果需要daemon.json需要自己创建daemon.json 即执行 touch /etc/docker/daemon.json 命令
{
"api-cors-header":"",
"authorization-plugins":[],
"bip": "",
"bridge":"",
"cgroup-parent":"",
"cluster-store":"",
"cluster-store-opts":{},
"cluster-advertise":"",
"debug": true, #启用debug的模式,启用后,可以看到很多的启动信息。默认false
"default-gateway":"",
"default-gateway-v6":"",
"default-runtime":"runc",
"default-ulimits":{},
"disable-legacy-registry":false,
"dns": ["192.168.1.1"], # 设定容器DNS的地址,在容器的 /etc/resolv.conf文件中可查看。
"dns-opts": [], # 容器 /etc/resolv.conf 文件,其他设置
"dns-search": [], # 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的 主机时,DNS不仅搜索host,还会搜
索host.example.com 。 注意:如果不设置, Docker 会默认用主机上的 /etc/resolv.conf 来配置容器。
"exec-opts": [],
"exec-root":"",
"fixed-cidr":"",
"fixed-cidr-v6":"",
"graph":"/var/lib/docker", #已废弃,使用data-root代替,这个主要看docker的版本
"data-root":"/var/lib/docker", #Docker运行时使用的根路径,根路径下的内容稍后介绍,默认/var/lib/docker 注:可以更改为自己的存储位置
"group": "", #Unix套接字的属组,仅指/var/run/docker.sock
"hosts": [], #设置容器hosts
"icc": false,
"insecure-registries": [“”], #配置docker的私库地址
"ip":"0.0.0.0",
"iptables": false,
"ipv6": false,
"ip-forward": false, #默认true, 启用 net.ipv4.ip_forward ,进入容器后使用 sysctl -a | grepnet.ipv4.ip_forward 查看
"ip-masq":false,
"labels":["nodeName=node-121"], # docker主机的标签,很实用的功能,例如定义:–label nodeName=host-121
"live-restore": true,
"log-driver":"",
"log-level":"",
"log-opts": {},
"max-concurrent-downloads":3,
"max-concurrent-uploads":5,
"mtu": 0,
"oom-score-adjust":-500,
"pidfile": "", #Docker守护进程的PID文件
"raw-logs": false,
"registry-mirrors":["xxxx"], #镜像加速的地址,增加后在 docker info中可查看。
"runtimes": {
"runc": {
"path": "runc"
},
"custom": {
"path":"/usr/local/bin/my-runc-replacement",
"runtimeArgs": [
"--debug"
]
}
},
"selinux-enabled": false, #默认 false,启用selinux支持
"storage-driver":"",
"storage-opts": [],
"swarm-default-advertise-addr":"",
"tls": true, #默认 false, 启动TLS认证开关
"tlscacert": "", #默认 ~/.docker/ca.pem,通过CA认证过的的certificate文件路径
"tlscert": "", #默认 ~/.docker/cert.pem ,TLS的certificate文件路径
"tlskey": "", #默认~/.docker/key.pem,TLS的key文件路径
"tlsverify": true, #默认false,使用TLS并做后台进程与客户端通讯的验证
"userland-proxy":false,
"userns-remap":""
}
原文:https://blog.csdn.net/u013948858/article/details/79974796
13或更改docker的镜像和容器的默认存储位置
注意:
13.1方法一 配置文件
- 停止docker服务
systemctl stop docker
默认位置/var/lib/docker,如果不改的话后期服务器的存储空间不够需要经常清理很麻烦,所以docker安装好后就更改,先用df -h查看哪个目录空间最大
2.在/data目录下面,/data目录大小有207G。 在 /data目录下面建了 /telecom/docker目录,执行的命令是:mkdir -p /data/telecom/docker
3、迁移/var/lib/docker目录下面的文件到 /data/telecom/docker下面
cp -R /var/lib/docker/* /data/telecom/docker/
注意:
如果文件内容很多的话,为了确保成功最好是一个文件一个文件的拷贝。如果在拷贝过程中报“设备上没有空间”的错误,就使用mv剪切。
4. 修改docker配置(供参考)
(/etc/systemd/system/docker.service.d/devicemapper.conf 路径不唯一根据配置文件位置而定),在文件末添加 --graph=/data/telecom/docker
执行rsync -avz /var/lib/docker /data/telecom/ 命令 同步
devicemapper.conf文件的内容如下:
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --insecure-registry=私服地址 --graph=/data/telecom/docker
注意:如果/etc/systemd/system/docker.service.d/devicemapper.conf,这个路径找不到的话,就新建,新建之后加入内容,没有私服地址的话就可以去掉”--insecure-registry=私服地址”。
重载配置,重启docker
systemctl daemon-reload;
systemctl restart docker;
systemctl enable docker;
13.2方法二、软链接
默认情况下Docker的存放位置为:/var/lib/docker
可以通过下面命令查看具体位置:
sudo docker info | grep "Docker Root Dir"
解决这个问题,最直接的方法当然是挂载分区到这个目录,但是数据盘还有其他东西,这肯定不好管理,所以采用修改镜像和容器的存放路径的方式达到目的。
这个方法里将通过软连接来实现。
首先停掉Docker服务:
systemctl stop docker
systemctl restart docker或者service docker stop
然后移动整个/var/lib/docker目录到目的路径:
mv /var/lib/docker /data/telecom/docker
ln -s /data/telecom/docker /var/lib/docker
确认文件夹类型为symlink 类型
ls -al /var/lib/docker
这时候启动Docker时发现存储目录依旧是/var/lib/docker,但是实际上是存储在数据盘的,你可以在数据盘上看到容量变化。
最后systemctl start docker
https://blog.csdn.net/qq_37674858/article/details/79976751
https://www.cnblogs.com/276815076/p/4673607.html
14 docker+harbor构建私有仓库
相关资料:https://blog.csdn.net/qq_35959573/article/details/80664353
1.安装docker-compose
1.1下载指定版本的docker-compose
网址 https://github.com/docker/compose/releases
1.2 上传包,解压
1.3 授予执行权限
chmod +x /data/telecom/k8s/compose-1.21.1/bin/docker-compose
1.4 查看版本
docker-compose --version
2 安装harbor-offline-installer-v1.5.1.tgz
2.1下载安装包
https://storage.googleapis.com/harbor-releases/release-1.5.0/harbor-offline-installer-v1.5.1.tgz
2.2 解压文件
解压tar xvf harbor-offline-installer-v1.5.1.tgz
2.3 进入解压目录
2.4 配置harbor.cfg配置文件
2.5 执行./install.sh
依次自动安装完成
2.6 在浏览器中访问
132.121.117.242:80/ 默认端口是80,可以在docker-compose.yml文件中修改端口
3 上传镜像到私有仓库
3.1后台登录仓库
# 登录仓库
docker login -u admin -p Harbor12345 132.121.117.242
私有仓库登陆成功
如果出现:
Error response from daemon: Get https://192.168.80.42/v1/users/: dial tcp 132.121.117.242:443: getsockopt: connection refused 错误
这是因为 docker1.3.2 版本开始默认 docker registry 使用的是 https,我们设置 Harbor 默认 http 方式,所以当执行用 docker login、pull、push 等命令操作非 https 的 docker regsitry 的时就会报错。解决办法:
如果系统是MacOS,则可以点击“Preference”里面的“Advanced”在“Insecure Registry”里加上192.168.80.42,重启Docker客户端就可以了;
如果系统是Ubuntu,则修改配置文件/lib/systemd/system/docker.service,修改[Service]下ExecStart参数,增加–insecure-registry 192.168.80.42
如果系统是Centos或RedHat,可以修改配置 /etc/systemd/system/docker.service,将 ExecStart 增加 –insecure-registry 132.121.117.242
或
在/etc/default/docker文件中加入--insecure-registry 132.121.117.242 私有仓库地址
3.2登出仓库
docker logout 132.121.117.242
3.3 浏览器访问
输入132.121.117.242:80/
3.5 新建镜像项目名
3.6 登录私有仓库
docker login 132.121.117.242
3.7打标签上传镜像
错误解决:
上图错误是没有加入私有或公有仓库镜像项目的名字 也等于是路径,这里取得项目名(telecom),如下图红框中
3.:8打标签
Docker tag打标签规则
Docker tag 本地镜像:版本号 ip或ip+端口/镜像项目名/镜像名:版本号
例:docker tag api_center2018120518008622:1.0 132.121.117.242/telecom/api_center2018120518008622:1.0
3.9 上传镜像
docker push 132.121.117.242/telecom/api_center2018120518008622:1.0
3.10 查看harbor的web页面是否成功
15 docker -v挂载
[telecom@master ~]$ docker run -d -v /data/telecom/logs:/data/telecom/mule/mule-standalone-3.8.1/logs --name api_center2018120518008622 -m 2048m --memory-swap=2048m -p 8622:8622 api_center2018120518008622:1.0
注意:
物理机的/data/telecom/logs目录与容器中/data/telecom/mule/mule-standalone-3.8.1/logs目录一致才有效,切记
同理文件共享的话可以-v挂载或在dockerfile中用
16 网络路由
241:Route add -net 172.17.0.1/16 gw 132.121.117.242
反之亦然
然后ping。如果不同 用iptables -F
17查看SELinux状态
/usr/sbin/sestatus -v
##如果SELinux status参数为enabled即为开启状态
18 harbor部署 SSL 认证
1) 概念理解
签名证书与自签名证书
签名证书:由权威颁发机构颁发给服务器或者个人用于证明自己身份的东西
自签名证书:由服务器自己颁发给自己,用于证明自己身份的东西,非权威颁发机构发布
openssl
openssl 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用
KEY与CSR的区别
Key通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER。证书自身拥有一个密钥对(即一个公钥和一个私钥),由公钥(Public Key)与私钥(Private Key)是通过一种算法得到,公钥是密钥对中公开的部分,私钥则是非公开的部分。一般公钥和密钥的关系为:1,公钥和私钥成对出现、2,公开的密钥叫公钥,只有自己知道的叫私钥、3,用公钥加密的数据只有对应的私钥可以解密、4,用私钥加密的数据只有对应的公钥可以解密、5,如果可以用公钥解密,则必然是对应的私钥加的密、6,如果可以用私钥解密,则必然是对应的公钥加的密
CSR文件必须在申请和购买SSL证书之前创建。也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请 者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书
2) 创建根证书
# 创建证书存放目录
mkdir -p /data/cert && cd /data/cert
[telecom@master ~]$ mkdir -p /data/cert && cd /data/cert
# 创建自己的CA证书(不使用第三方权威机构的CA来认证,自己充当CA的角色)
openssl genrsa -out ca.key 2048 # 生成根证书私钥(无加密)
[telecom@master cert]$ openssl genrsa -out ca.key 2048
# 生成自签名证书(使用已有私钥ca.key自行签发根证书)
openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj “/CN=Harbor-ca”
req 产生证书签发申请命令
-x509 签发X.509格式证书命令。X.509是最通用的一种签名证书格式。
-new 生成证书请求
-key 指定私钥文件
-nodes 表示私钥不加密
-out 输出
-subj 指定用户信息
-days 有效期
[telecom@master cert]$ openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj '/CN=Harbor-ca'
3) 创建服务器端证书
# 生成服务器端私钥和CSR签名请求
openssl req -newkey rsa:4096 -nodes -sha256 -keyout server.key -out server.csr # 一路回车
[telecom@master cert]$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout server.key -out server.csr
# 签发服务器证书
echo subjectAltName = IP:132.121.117.242 > extfile.cnf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extfile extfile.cnf -out server.crt
x509 签发X.509格式证书命令。
-req 表示证书输入请求。
-days 表示有效天数
-extensions 表示按OpenSSL配置文件v3_req项添加扩展。
-CA 表示CA证书,这里为ca.crt
-CAkey 表示CA证书密钥,这里为ca.key
-CAcreateserial 表示创建CA证书序列号
-extfile 指定文件
[telecom@master cert]$ echo subjectAltName = IP:132.121.117.242 > extfile.cnf
[telecom@master cert]$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extfile extfile.cnf -out server.crt
4) 修改 Harbor 的配置文件 hardor.cfg
# 修改成 https
ui_url_protocol = https
# 认证文件的路径
ssl_cert = /data/cert/server.crt
ssl_cert_key = /data/cert/server.key
5) 设置 docker 证书
# 如果如下目录不存在,请创建,如果有域名请按此格式依次创建 mkdir -p /etc/docker/certs.d/192.168.80.42 # mkdir -p /etc/docker/certs.d/[IP2] # mkdir -p /etc/docker/certs.d/[example1.com]
# 如果端口为443,则不需要指定。如果为自定义端口,请指定端口
# /etc/docker/certs.d/yourdomain.com:port
[telecom@master cert]$ mkdir -p /etc/docker/certs.d/132.121.117.242
[telecom@master cert]$ ls -l /etc/docker/certs.d/
# 将 ca 根证书依次复制到上述创建的目录中
[telecom@master cert]$ cp ca.crt /etc/docker/certs.d/132.121.117.242
[telecom@master cert]$
[telecom@master cert]$ cp server.crt /etc/docker/certs.d/132.121.117.242
6)重启docker和 重启动Harbor
# 重启 docker
systemctl restart docker
# 启动Harbor
./install.sh
19 docker容器设置时区时间,中文乱码
Docker应用时区与服务器时间同步(dockerfile)
时间:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
设置中文乱码:
ENV LANG=en_US.UTF-8
ENV TZ=Asia/Shanghai
Dockerfile
20.Dockerfile的简介
Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制额外的需求时,只需Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。
20.1设置时区时间,中文乱码
Docker应用时区与服务器时间同步(dockerfile)
时间:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
设置中文乱码:
ENV LANG=en_US.UTF-8
ENV TZ=Asia/Shanghai
Dockerfile文件中的CMD和ENTRYPOINT指令差异对比
http://www.cnblogs.com/lienhua34/p/5170335.html
CMD指令和ENTRYPOINT指令的作用都是为镜像指定容器启动后的命令,那么它们两者之间有什么各自的优点呢?
为了更好地对比CMD指令和ENTRYPOINT指令的差异,我们这里再列一下这两个指令的说明,
20.2 CMD
支持三种格式
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
20.3 ENTRYPOINT
两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中执行)。
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
从上面的说明,我们可以看到有两个共同点:
都可以指定shell或exec函数调用的方式执行命令;
当存在多个CMD指令或ENTRYPOINT指令时,只有最后一个生效;
而它们有如下差异:
差异1:CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖,而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
差异2:CMD指令可以为ENTRYPOINT指令设置默认参数,而且可以被docker run指定的参数覆盖;
下面分别对上面两个差异点进行详细说明,
4.1 差异1
CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖;而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
下面有个命名为startup的可执行shell脚本,其功能就是输出命令行参数而已。内容如下所示,
#!/bin/bash
echo "in startup, args: $@"
通过CMD指定容器启动时命令:
现在我们新建一个Dockerfile文件,其将startup脚本拷贝到容器的/opt目录下,并通过CMD指令指定容器启动时运行该startup脚本。其内容如下,
复制代码
FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com
ADD startup /opt
RUN chmod a+x /opt/startup
CMD ["/opt/startup"]
复制代码
通过运行docker build命令生成test:latest镜像,然后使用docker run启动两个test:latest镜像的容器,第一个docker run命令没有指定容器启动时命令,第二个docker run命令指定了容器启动时的命令为“/bin/bash -c 'echo Hello'”,
lienhua34@test$ sudo docker run -ti --rm=true test
in startup, args:
lienhua34@test$ sudo docker run -ti --rm=true test /bin/bash -c 'echo Hello'
Hello
从上面运行结果可以看到,docker run命令启动容器时指定的运行命令覆盖了Dockerfile文件中CMD指令指定的命令。
通过ENTRYPOINT指定容器启动时命令:
将上面的Dockerfile中的CMD替换成ENTRYPOINT,内容如下所示,
复制代码
FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com
ADD startup /opt
RUN chmod a+x /opt/startup
ENTRYPOINT [“/opt/startup”]
复制代码
同样,通过运行docker build生成test:latest镜像,然后使用docker run启动两个test:latest镜像的容器,第一个docker run命令没有指定容器启动时命令,第二个docker run命令指定了容器启动时的命令为“/bin/bash -c 'echo Hello'”,
lienhua34@test$ sudo docker run -ti --rm=true test
in startup, args:
lienhua34@test$ sudo docker run -ti --rm=true test /bin/bash -c 'echo Hello'
in startup, args: /bin/bash -c echo Hello
通过上面的运行结果可以看出,docker run命令指定的容器运行命令不能覆盖Dockerfile文件中ENTRYPOINT指令指定的命令,反而被当做参数传递给ENTRYPOINT指令指定的命令。
4.2 差异2
CMD指令可以为ENTRYPOINT指令设置默认参数,而且可以被docker run指定的参数覆盖;
同样使用上面的startup脚本。编写Dockerfile,内容如下所示,
复制代码
FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com
ADD startup /opt
RUN chmod a+x /opt/startup
ENTRYPOINT ["/opt/startup", "arg1"]
CMD ["arg2"]
复制代码
运行docker build命令生成test:latest镜像,下面运行docker run启动两个test:latest镜像的容器,第一条docker run命令没有指定参数,第二条docker run命令指定了参数arg3,其运行结果如下,
lienhua34@test$ sudo docker run -ti --rm=true test
in startup, args: arg1 arg2
lienhua34@test$ sudo docker run -ti --rm=true test arg3
in startup, args: arg1 arg3
从上面第一个容器的运行结果可以看出CMD指令为ENTRYPOINT指令设置了默认参数;从第二个容器的运行结果看出,docker run命令指定的参数覆盖了CMD指令指定的参数。
4.3注意点
CMD指令为ENTRYPOINT指令提供默认参数是基于镜像层次结构生效的,而不是基于是否在同个Dockerfile文件中。意思就是说,如果Dockerfile指定的基础镜像中是ENTRYPOINT指定的启动命令,则该Dockerfile中的CMD依然是为基础镜像中的ENTRYPOINT设置默认参数。
例如,我们有如下一个Dockerfile文件,
复制代码
FROM ubuntu:14.04
MAINTAINER lienhua34@xxx.com
ADD startup /opt
RUN chmod a+x /opt/startup
ENTRYPOINT ["/opt/startup", "arg1"]
复制代码
通过运行docker build命令生成test:0.0.1镜像,然后创建该镜像的一个容器,查看运行结果,
复制代码
lienhua34@test$ sudo docker run -ti --rm=true test:0.0.1
in startup, args: arg1
复制代码
下面新建一个Dockerfile文件,基础镜像是刚生成的test:0.0.1,通过CMD指定要通过echo打印字符串“in test:0.0.2”。文件内容如下所示,
FROM test:0.0.1
MAINTAINER lienhua34@xxx.com
CMD ["/bin/bash", "-c", "echo in test:0.0.2"]
运行docker build命令生成test:0.0.2镜像,然后通过运行docker run启动一个test:0.0.2镜像的容器来查看结果,
复制代码
lienhua34@test$ sudo docker run -ti --rm=true test:0.0.2
in startup, args: arg1 /bin/bash -c echo in test:0.0.2
复制代码
从上面结果可以看到,镜像test:0.0.2启动的容器运行时并不是打印字符串”in test:0.0.2”,而是将CMD指令指定的命令当做基础镜像test:0.0.1中ENTRYPOINT指定的运行脚本startup的参数。
Dockerfile文件的说明:
格式:
INSTRUCTION arguments
虽然指令忽略大小写,但建议用大写
# 是注释
MAINTAINER命令:
MAINTAINER命令用来指定维护者的姓名和联系方式
FROM命令:
FROM <image>/<image>:<tag>
这个是设置基本的镜像,为后续的命令使用,所以应该作为Dockerfile的第一条指令
比如:
FROM centos6-base
RUN 命令:
会上面FROM 指定的镜像里执行任何命令,然后提交(commit)结果,提交的镜像会在后面继续用到
格式:
RUN <command> (这个命令运行一个shell中 - '/bin/sh -c')
或:
RUN ["executable", "param1", "param2"]
RUN 命令等价于:
docker run image_name command
CMD and ENTRYPOINT
命令设置在容器启动时执行命令
ENTRYPOINT,表示镜像在初始化时需要执行的命令,不可被重写覆盖,需谨记
CMD,表示镜像运行默认参数,可被重写覆盖
注意切记:
1.ENTRYPOINT/CMD都只能在文件中存在一次,并且最后一个生效 多个存在,只有最后一个生效,其它无效!
需要初始化运行多个命令,彼此之间可以使用 && 隔开,但最后一个须要为无限运行的命令,需切记!
ENTRYPOINT/CMD,一般两者可以配合使用,比如:
ENTRYPOINT ["/usr/sbin/sshd"]
CMD ["-D"]
在Docker daemon模式下,无论你是使用ENTRYPOINT,还是CMD,最后的命令,一定要是当前进程需要一直运行的,才能够防容器退出。
以下无效方式:
ENTRYPOINT service tomcat7 start #运行几秒钟之后,容器就会退出
CMD service tomcat7 start #运行几秒钟之后,容器就会退出
这样有效:
ENTRYPOINT service tomcat7 start && tail -f /var/lib/tomcat7/logs/catalina.out
# 或者
CMD service tomcat7 start && tail -f /var/lib/tomcat7/logs/catalina.out
这样也有效:
ENTRYPOINT ["/usr/sbin/sshd"]
CMD ["-D"]
USER 命令
比如指定 memcached 的运行用户,可以使用上面的 ENTRYPOINT or CMD来实现:
ENTRYPOINT ["memcached", "-u", "daemon"]
更好的方式:
ENTRYPOINT ["memcached"]
USER daemon
EXPOSE 命令
EXPOSE 命令可以设置一个端口在运行的镜像中暴露在外
在docker使用--link来链接两容器时会用到相关端口
EXPOSEd <port>
ENV命令:
用于设置环境变更
使用此dockerfile生成的image新建container,可以通过 docker inspect CONTAINER ID 看到这个环境变量
也可以通过在docker run时设置或修改环境变量
ADD 命令:
从src复制文件到container的dest路径:
ADD <src> <dest>
<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url
<dest> 是container中的绝对路径
VOLUME 命令
VOLUME ["<mountpoint>"]
如:
VOLUME ["/data"]
创建一个挂载点用于共享目录
WORKDIR 命令
WORKDIR /path/to/workdir
配置RUN, CMD, ENTRYPOINT 命令设置当前工作路径
可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令
比如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
其实是在 /a/b/c 下执行 pwd