Cetnos7Docker使用遇到的问题

yum安装[[Docker]]

官方安装文档 主要是以下几步

yum remove docker docker-common docker-selinux docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce

私有[[../Harbor-容器镜像仓库|Harbor]]仓库,http,或镜像服务器地址修改

docker 18.09+ 配置私有仓库不再是使用/etc/docker/daemon.json文件,而是修改/usr/lib/systemd/system/docker.service 文件

vi /usr/lib/systemd/system/docker.service 
	……
	ExecStart=/usr/bin/dockerd --insecure-registry 172.25.0.50	# 修改此行为该格式
	……
systemctl daemon-reload
systemctl restart docker
docker login 172.25.0.50

14+ 到18.0

修改“/etc/docker/daemon.json”文件(如果没有,可以手动创建),在该文件内添加如下内容: vi /etc/docker/daemon.json

{ "registry-mirrors": ["加速器地址"] }

之前的版本可以用以下方式

curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://5afd41fb.m.daocloud.io

该脚本可以将 --registry-mirror 加入到你的 Docker 配置文件 /etc/default/docker 中。适用于 Ubuntu14.04、Debian、CentOS6 、CentOS7、Fedora、Arch Linux、openSUSE Leap 42.1,其他版本可能有细微不同。

二进制安装

二进制包下载路径:https://download.docker.com/linux/static/stable/

wget https://download.docker.com/linux/static/stable/x86_64/docker-27.1.2.tgz

tar -zxf docker-27.1.2.tgz

cp docker/* /usr/bin/

vi /etc/systemd/system/docker.service

[Unit]
Description=Docker CE

[Service]
ExecStart=/usr/bin/dockerd
Restart=on-failure
RestartSed=10s

[Install]
WantedBy=multi-user.target

服务控制

systemctl daemon-reload

systemctl enable docker
systemctl start docker

使用

映射本地目录到容器中需要在创建容器时就映射,命令如下:

docker run -i -t -d -v /usr/src/html:/var/www/html --name apache txdier/apache /bin/bash

将本地的/usr/src/html目录映射到容器apache的/var/www/html目录,apache是定义的容器名称 txdier/apache 是我自己创建的镜像名称 /bin/bash是容器创建后运行的环境为shell环境。

映射容器端口到本地端口

docker run -d -p 80:8081 --name apache txdier/apache /bin/bash

以上命令为映射容器apache的8081端口到本地80商品,主要是参数-p(小写),前面为本地端口,后面是容器端口。 如果是容器已经创建,映射端口的方法为:

iptables -t nat -A DOCKER -p tcp --dport 80 -j DNAT --to-destination 172.17.0.6:8081

在iptables 的NAT表中创建一个DOCKER链,并将访问本地80端口的流量转到172.17.0.6(apache容器IP,可以通过docker inspect apache来查看)IP的8081端口

如果上面的映射端口不需要了,可以将上面命令的A改成D来删除,例如:

iptables -t nat -D DOCKER -p tcp --dport 80 -j DNAT --to-destination 172.17.0.6:8081

firewalld常用命令 --permanent永久生效,没有此参数重启后失效

firewall-cmd --zone=public --add-port=80/tcp		#开放tcp80端口
firewall-cmd --zone=pubic --remove-port=80/tcp	#关闭tcp80端口

改配置文件后 使用命令重新加载

firewall-cmd --reload

开放某个服务

firewall-cmd --zone=public --add-service=https   //临时
firewall-cmd --permanent --zone=public --add-service=https  //永久

开启某个端口

firewall-cmd --permanent --zone=public --add-port=8080-8081/tcp  //永久
firewall-cmd  --zone=public --add-port=8080-8081/tcp   //临时

使用命令加载设置

firewall-cmd --reload

查看开启的端口和服务

firewall-cmd --permanent --zone=public --list-services    //服务空格隔开  例如 dhcpv6-client https ss  
firewall-cmd --permanent --zone=public --list-ports //端口空格隔开  例如  8080-8081/tcp 8388/tcp 80/tcp

制作tomcat镜像,需要提前准备好tomcat的源码

# AlpineLinux with a glibc-2.25 and Oracle Java 7.0.67 and tomat 7.0.73
FROM alpine:latest
MAINTAINER Anastas Dancha <[email protected]>
ENV	JAVA_VERSION_MAJOR=7 \
		JAVA_VERSION_MINOR=67 \
		JAVA_PACKAGE=jdk \
		JAVA_HOME=/opt/jdk \
	 PATH=${PATH}:/opt/jdk/bin 
COPY glibc-2.25-r0.apk /opt/
COPY jdk1.7.0_76 /opt/jdk1.7.0_76
RUN	apk upgrade --update && \
	 apk add --update libstdc++ ca-certificates bash && \
		apk add --allow-untrusted /opt/*.apk && \
		rm -v /opt/*.apk && \
	ln -s /opt/jdk1.7.0_76 /opt/jdk 
#CMD ["java", "-version"]
# install tomcat7.0.73
ENV	TOMCAT_HOME=/opt/tomcat \
		CATALINA_HOME=/opt/tomcat \
		CATALINA_OUT=/dev/null \
	CATALINA_OPTS="-Xms1024m -Xmx2048m -Xmn768m -Xss2m -XX:NewSize=512M -XX:MaxNewSize=512m  -XX:PermSize=512M -XX:MaxPermSize=1024m -XX:-UseSplitVerifier -Duser.timezone=GMT+08"
COPY tomcat /opt/tomcat
COPY logging.properties ${TOMCAT_HOME}/conf/logging.properties
COPY server.xml ${TOMCAT_HOME}/conf/server.xml
ENV PATH /opt/tomcat/bin
CMD ["catalina.sh", "run"]
VOLUME ["/logs"]
EXPOSE 8080
#END

监控docker容器CPU、MEM、NET、IO 等信息建议用ctop,下载地址https://github.com/bcicen/ctop/

用Ctrl+C退出

打包镜像(保存、导出镜像)

docker images
	REPOSITORY			TAG  		 IMAGE ID			CREATED			SIZE
	redis-cluster--v1   latest		0e0ca6098731		6 days ago		445MB

docker save 0e0ca6098731 > redis-3.2.9-cluster.tar
ls 
	redis-3.2.9-cluster.tar

导入镜像,复制之前的redis-3.2.9-cluster.tar文件到需要导入的服务器

docker load < redis-3.2.9-cluster.tar
docker images
docker tag 0e0ca6098731 redis-cluster:3.2.9
docker images

将容器制作成镜像

docker commit -m "log" aa63cb4d8a9d test:latest		#aa63cb4d8a9d是CONTAINER ID
docker run -d --name test test:latest	# 用之前容器转成的镜像生成一个新的容器

镜像导入和容器导入的区别: 1)容器导入 是将当前容器 变成一个新的镜像 2)镜像导入 是复制的过程 save 和 export区别: 1)save 保存镜像所有的信息-包含历史 2)export 只导出当前的信息

DOCKER WEB管理工具 portainer

website: https://portainer.io

安装、运行

docker volume create portainer_data
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

kubernetes yum 源(阿里云)

vi /etc/yum.repos.d/kubernetes.repo
	[kubernetes]
	name=Kubernetes
	baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
	enabled=1
	gpgcheck=0
	repo_gpgcheck=0
	gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

docker 容器时间跟机器时间不一至,挂载以下文件进行同步(centos7+)

-v /etc/localtime:/etc/localtime:ro

更改docker存储目录

思路:停止docker 移动原目录至新目录,将新路径通过软件链接至原路径,启动dokcer,启动docker所有容器

systemctl stop docker && mv /var/lib/docker /data/ && ln -s /data/docker /var/lib/docker && systemctl start docker && docker start `docker ps -aq`

搭建本地仓库

docker run -d -p 5000:5000 --restart=always -v /data/registry:/tmp/registry --name docker_local_registry registry
docker images
docker tag tomcat 172.16.73.248:5000/tomcat
docker push 172.16.73.248:5000/tomcat

http: server gave HTTP response to HTTPS client

出现这问题的原因是:Docker自从1.3.X之后docker registry交互默认使用的是HTTPS,但是搭建私有镜像默认使用的是HTTP服务,所以与私有镜像交时出现以上错误。 解决办法是:在docker server启动的时候,增加启动参数,默认使用HTTP访问:

vim /usr/lib/systemd/system/docker.service #大约12行
systemctl daemon-reload && systemctl restart docker && docker start `docker ps -aq`

停止注册表并删除所有数据

docker container stop docker_local_registry && docker container rm -v docker_local_registry

解决无法删除状态为Dead的容器

docker stop nginx 1>/dev/null 2>&1 | exit 0
docker rm -f nginx 1>/dev/null 2>&1 | exit 0

添加容器健康状态检查

第一种方法:在Dockerfile中添加HEALTHCHECK,需要安装[[curl命令|curl]] HEALTHCHECK --interval=5s --timeout=2s --retries=12 CMD curl --silent --fail localhost:9200/_cluster/health || exit 1

第二种方法:镜像已经创建好,可以在创建容器时指定健康检查参数

docker run -d \
--health-cmd="curl --silent --fail localhost:9200/_cluster/health || exit 1" \ 
--health-interval=5s \ 
--health-retries=12 \ 
--health-timeout=2s \ 
--name tomcat \
tomcat:latest

修改容器时间

容器内部时间一般不与本机同步,需要手动调整,可以通过 -v 将本机的/etc/localtime或/etc/timezone挂载至容器内,示例如下: 最后的ro表示readonly

docker run -d -v /etc/localtime:/etc/localtime:ro java 
docker run -d -v /etc/timezone:/etc/timezone:ro java

大部分容器挂载/etc/localtime即可同步容器和本机时间,也有部分容器(例如java镜像)通过localtime就会无效,需要同步timezone文件,先看一下本机的timezone文件内容,我的timezone内容如下

cat /etc/timezone
	Asia/Shanghai

docker支持如下restart策略:

参数
描述

no

容器退出时不要自动重启。这个是默认值。

on-failure[:max-retries]

只在容器以非0状态码退出时重启。可选的,可以退出docker daemon尝试重启容器的次数。

always

不管退出状态码是什么始终重启容器。当指定always时,docker daemon将无限次数地重启容器。容器也会在daemon启动时尝试重启,不管容器当时的状态如何。

unless-stopped

不管退出状态码是什么始终重启容器,不过当daemon启动时,如果容器之前已经为停止状态,不要尝试启动它。

在每次重启容器之前,不断地增加重启延迟[上一次重启的双倍延迟,从100毫秒开始]来防止影响服务器。这意味着daemon将等待100ms,然后200 ms, 400, 800, 1600等等,直到超过on-failure限制,或执行docker stop或docker rm -f。 如果容器重启成功[容器启动后并运行至少10秒],然后delay重置为默认的100ms。 你可以使用on-failure策略指定docker尝试重启容器的最大次数。默认下docker将无限次数重启容器。可以通过docker inspect来查看已经尝试重启容器了多少次。例如,获取容器“my-container”的重启次数:

docker inspect -f "{{ .RestartCount }}" my-container

获取上一次容器重启时间:

docker inspect -f "{{ .State.StartedAt }}" my-container

示例:

docker run --restart=on-failure:10 redis	# restart策略为on-failure,最大重启次数为10的redis容器。如果redis以非0状态退出连续退出超过10次,那么docker将中断尝试重启这个容器。只有on-failure策略支持设置最大重启次数限制。

清理docker容器日志

容器运行久了,会产生很多日志,需要对日志文件进行清理,减少日志对磁盘的占用,docker容器日志存放位置为/var/lib/docker的 *-json.log 查找出所有容器的日志文件,并显示占用空间

ls -lh `find /var/lib/docker/containers/ -name *-json.log`

清理占用空间较大的日志文件

cat /dev/null > /var/lib/docker/containers/bf1e02dd14678116d299952bdf2af20e42cd5a3af654524279350948843c8f9b/bf1e02dd14678116d299952bdf2af20e42cd5a3af654524279350948843c8f9b-json.log

批量清理脚本

#! /bin/bash
logsfile=`find /var/lib/docker/containers/ -name *-json.log`
for log in $logsfile;
	do
		echo -e "clean log file: $log"
		cat /dev/null > $log
	done

docker run增加如下参数,限制生成的json.log单个文件大小和保留文件个数:

--log-opt max-size=10m --log-opt max-file=3

镜像修剪

docker system prune  # 命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)
docker system prune -a # 命令清理得更加彻底,可以将没有容器使用Docker镜像都删掉。

显示镜像名完整格式

要显示 Docker 镜像的名称和标签拼接在一起的格式,可以使用 docker images 命令并通过 awk 或其他工具来格式化输出

# 显示所有
docker images --format "{{.Repository}}:{{.Tag}}"

# 显示指定关键字的
docker images | grep gitlab | awk '{print $1":"$2}'

# 如果有多行,不显示第一行,用(NR>1)来跳过第一行
docker images | grep gitlab | awk '{if(NR>1) print $1":"$2}'

错误处理

docker 服务启动容器后agetty进程 cpu占用率达到 100%

引起这个问题的原因是在使用 "docker run"运行容器时使用了 "/sbin/init"和 "--privileged"参数。

使用 /sbin/init启动容器并加上 --privileged参数,相当于 docker容器获得了宿主机的全权委托权限。这时 docker容器内部的 init与宿主机的 init产生了混淆。

出于对安全的考虑,在启动容器时, docker容器里的系统只具有一些普通的 linux权限,并不具有真正 root用户的所有权限。而 --privileged=true参数可以让 docker容器具有 linux root用户的所有权限。

为了解决这个问题, docker后来的版本中 docker run增加了两个选项参数 "--cap-add"和 "--cap-drop"。

  • --cap-add : 获取 default之外的 linux的权限

  • --cap-drop: 放弃 default linux权限

所以,在运行容器时,可以不用 --privileged参数的尽量不用,用 --cap-add参数替代。如果必须使用 --privileged=true参数的,可以通过在宿主机和容器中执行以下命令将 agetty关闭。

systemctl stop [email protected]
systemctl mask [email protected]

CentOS 7下使用类似nginx之类的web server,启动docker时有时会报以下错误:

docker0: iptables: No chain/target/match by that name.

解决方法:

systemctl docker restart

重启docker后:

iptables -L

可以看到iptables里面多出了Chain Docker的选项。

经验为:在启动firewalld之后,iptables被激活,此时没有docker chain,重启docker后被加入到iptable里面。

error pulling image configuration: download failed after attempts=6: tls: failed to verify certificate: x509: certificate has expired or is not yet valid: current time 2024-01-23T11:09:25+08:00 is after 2021-09-30T14:01:15Z

CentOS7 拉取镜像提示证书过期,需要更新一下系统本地的CA证书

yum install ca-certificates
update-ca-trust force-enable
update-ca-trust extract

最后更新于