[root@linux-node1 ~]# cd /etc/yum.repos.d/
[root@linux-node1 yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce
docker分企业版(EE)和社区版(CE),社区版免费,企业版收钱,两个版本更新速度不一样。
systemctl start docker
[root@k8s-master ~]# docker search centos
NAME DESCRIPTION STARS OFFICIAL<是否为docker官方发布> AUTOMATED
centos The official build of CentOS. 6789 [OK]
docker run centos<镜像名称> /bin/echo 'HE' <要在容器执行的指令>
创建并进入容器内部: -it
[root@linux-node1 ~]#docker run --name mydocker -it centos /bin/bash
[root@1b0cae722fa0 /]#
让容器后台运行
[root@linux-node1 ~]# docker run -d --name mydocker2 centos /bin/bash
容器已经创建但是未启动
[root@linux-node2 maiyp]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20273b3451bf centos "/bin/bash" 9 hours ago Exited (0) 3 seconds ago mypdocker
[root@linux-node2 maiyp]# docker start mypdocker
mypdocker
[root@linux-node2 maiyp]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20273b3451bf centos "/bin/bash" 9 hours ago Up 19 seconds mypdocker
docker attach mydocker
nsenter
使用nsenter可以访问另一个进程的名字空间
先获取容器的第一个进程的PID,然后通过PID进入容器
PID=$( docker inspect --format "{{ .State.Pid }}" <容器名或ID>) )
#如果容器没有启动,PID为0
nsenter --target $PID --mount --uts --ipc --net --pid
通过脚本进入容器
[root@linux-node2 maiyp]# cat docker_in.sh
#!/bin/bash
docker_in(){
docker_nm=$1
docker_pid=$( docker inspect --format "{{ .State.Pid }}" $docker_nm)
if [ $docker_pid -eq 0 ]
then
echo "the docker is not starting!"
exit -1
fi
nsenter --target $docker_pid --mount --uts --ipc --net --pid
}
docker_in $1
[root@linux-node2 maiyp]# ./docker_in.sh mypdocker
[root@20273b3451bf /]#
#主机名为容器ID前几位
通过exec进入容器
[root@linux-node1 ~]# docker exec mydocker whoami
root
#不进入容器执行命令
[root@linux-node2 maiyp]# docker exec -it mypdocker /bin/bash
[root@20273b3451bf /]#
#进入容器执行命令
使用docker exec、nsenter进入容器后,执行exit退出容器,容器并不会关闭。但是使用docker attach进入容器,输入exit退出容器后,容器也会自动终止。因为除了attach,nsenter和exec实际中都是开了一个新的shell在执行。而attach是使用容器本身启动的/bin/bash,这个shell环境退出了。那么容器就自动退出了。
(1)FROM
基础镜像,必须是可以下载下来的,定制的镜像都是基于 FROM 的镜像,这里的 centos就是定制需要的基础镜像。
(2)MAINTAINER
指定镜像的作者信息
(3)RUN
指定在当前镜像构建过程中要运行的命令
包含两种模式
1、Shell
RUN (shell模式,这个是最常用的,需要记住)
RUN echo hello
2、exec模式
RUN “executable”,“param1”,“param2”
RUN [“/bin/bash”,”-c”,”echo hello”]
等价于/bin/bash -c echo hello
(4)EXPOSE指令
仅仅只是声明端口。
作用:
1、帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
2、在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
3、可以是一个或者多个端口,也可以指定多个EXPOSE
格式:EXPOSE <端口1> [<端口2>…]
(5)CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
1、CMD 在docker run 时运行。
2、RUN 是在 docker build构建镜像时运行的
作用:
为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
CMD[“executable”,“param1”,“param2”](exec模式)
CMD command (shell模式)
CMD [“param1”,”param2”] (作为ENTRYPOINT指令的默认参数)
例如:CMD ["/usr/sbin/nginx","-g",“daemon off;”]
(6)ENTERYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
格式:
ENTERYPOINT [“executable”,“param1”,“param2”] (exec模式)
ENTERYPOINT command (shell模式)
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。
示例:
假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT [“nginx”, “-c”] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
1、不传参运行
$ docker run nginx:test
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
2、传参运行
$ docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf
(7)COPY
COPY…
COPY[“”…“”]
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
COPY [–chown=:] <源路径1>… <目标路径>
COPY [–chown=:] “<源路径1>”,… “<目标路径>”
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
(8)ADD
ADD …
ADD [“”…“”]
ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
ADD vs COPY
ADD包含类似tar的解压功能
如果单纯复制文件,dockerfile推荐使用COPY
(9)VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
1、避免重要的数据,因容器重启而丢失,这是非常致命的。
2、避免容器不断变大。
格式:
VOLUME ["<路径1>", “<路径2>”…]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
VOLUME [“/data”]
(10)WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:
WORKDIR <工作目录路径>
WORKDIR /path/to/workdir
(填写绝对路径)
(11 )ENV
设置环境变量
ENV
ENV =…
以下示例设置 NODE_VERSION =6.6.6, 在后续的指令中可以通过 $ NODE_VERSION
(12)USER
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:
USER <用户名>[:<用户组>]
USER daemon
USER nginx
USER user
USER uid
USER user:group
USER uid:gid
USER user:gid
USER uid:group
#1.Dockerfile
vim Dockerfile >> EOF
#base image
FROM centos
#Who
MAINTAINER xxx
RUN yum install nginx -y
RUN mkdir -p /var/www/html
COPY index.html /usr/share/nginx/html
# Outside Port
EXPOSE 80
#启动nginx服务
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
<<EOF
#2.构建镜像
docker build -t "nginx/xxx:v1" .
#3.使用镜像构建容器
docker run -d --name nginx_test -p 80 nginx/xxx:v1 #此时因为容器没有进程夯住容器,所以容器是stop状态
#4. 启动容器并进入
docker start nginx_test && docker exec -it nginx_test /bin/bash
docker镜像一般是从dockerhub中下载,dockerhub是docker官方的镜像仓库。不过我们在使用的过程中,会逐渐产生适配自己环境的镜像,因此可以搭建一个私有仓库来存放镜像。私有仓库一般使用registry搭建。
私有仓库的主机IP:172.31.0.25
docker pull registry
#从dockerhub中拉取registry镜像
docker run -d registry -p 5000:5000 -v /opt/registry:/var/lib/registry registry:latest
#registry容器中的镜像会保留在目录/var/lib/registry中,为了防止删除容器之后,镜像也被删除。需要挂载本地目录/opt/registry到容器中,/opt/registry目录会自动在本机创建
[root@k8s-node1 docker]# ls /opt/registry
[root@k8s-node1 docker]#
[root@k8s-node1 docker]# curl http://172.31.0.25:5000/v2/_catalog
{"repositories":[]} #镜像列表还是空的
修改 /etc/docker/daemon.json文件,加入"insecure-registries": ["172.31.0.25:5000"]
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"],
"insecure-registries": ["172.31.0.25:5000"]
}
# --insecure-registry 一般安全传输镜像,需要使用https协议。我们的私有仓库一般是局域中使用,所以直接使用http协议就可以了。
#注意第一行后的逗号,没加上导致docker 起不来。具体看六、Docker故障排查
#重新加载,使配置生效 && 重启服务
systemctl daemon-reload && systemctl restart docker.service
[root@k8s-master ~]# docker images |grep busybox
busybox
[root@k8s-master ~]# docker tag busybox 172.31.0.25:5000/busybox:v1
[root@k8s-master ~]# docker images |grep busybox
172.31.0.25:5000/busybox v1 42b97d3c2ae9 7 weeks ago 1.24MB
busybox
[root@k8s-master ~]# docker push 172.31.0.25:5000/busybox:v1
The push refers to repository [172.31.0.25:5000/busybox]
0fd05bf2930d: Pushed
v1: digest: sha256:b862520da7361ea093806d292ce355188ae83f21e8e3b2a3ce4dbdba0a230f83 size: 527
[root@k8s-master ~]# curl http://172.31.0.25:5000/v2/_catalog
{"repositories":["busybox"]}
登录私有仓库主机查看/opt/registry目录
[root@k8s-node1 repositories]# ll
total 0
drwxr-xr-x 5 root root 55 Oct 11 22:26 busybox
[root@k8s-node1 repositories]# pwd
/opt/registry/docker/registry/v2/repositories
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,Harbor提供了更好的性能和安全。
硬件
硬件 | 最低要求 | 本文使用规格 |
---|---|---|
CPU | 2 CPU | 2 CPU |
内存 | 4 GB | 4 GB |
硬盘 | 40 GB | 40 GB |
软件
软件 | 版本 | 本文使用版本 |
---|---|---|
dcoker | 17.06.0-ce+或更高 | Docker version 20.10.8 |
Docker Compose | 1.18.0或更高 | docker-compose version 1.18.0 |
说明
说明 | 规划 |
---|---|
内网IP | 172.31.0.25 |
外网IP | 117.xx.xx.xx |
主机名 | k8s-node1 |
由于部署机器为云主机,使用443端口有风险,修改端口为1443
-new:表示生成一个新证书签署请求
-x509:专用于CA生成自签证书,如果不是自签证书则不需要此项
-key:生成请求时用到的私钥文件
-out:证书的保存路径
-days:证书的有效期限,单位是day(天),默认是365天
openssl genrsa -out ca.key 3072 #生成一个3072位的私钥
生成数字证书ca.pem
openssl req -new -x509 -days 3650 -key ca.key -out ca.pem
openssl genrsa -out harbor.key 3072 #生成一个3072位的私钥
生成一个证书请求,一会签发证书时需要的
#openssl req -new -key harbor.key -out [主机名].csr
[root@k8s-node1 /data/ssl/]# openssl req -new -key harbor.key -out k8s-node1.csr
#openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out [主机名].pem -days 3650
[root@k8s-node1 /data/ssl/]# openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out k8s-node1.pem -days 3650
mkdir -p /data/cert/
cp /data/ssl/k8s-node1.pem /data/cert/
cp /data/ssl/k8s-node1.key /data/cert/
[root@k8s-node1 /data/ssl/]# openssl x509 -inform PEM -in k8s-node1.crt -out k8s-node1.cert
[root@k8s-node1 /data/ssl/]# mkdir -p /etc/docker/certs.d/k8s-node1/
[root@k8s-node1 /data/ssl/]# cp k8s-node1.cert /etc/docker/certs.d/k8s-node1/
[root@k8s-node1 /data/ssl/]# cp k8s-node1.key /etc/docker/certs.d/k8s-node1/
[root@k8s-node1 /data/ssl/]# systemctl restart docker
下载安装包
从GitHub上下载harbor安装包,建议下载offline的压缩包,里面包含了harbor启动所用的所有docker镜像,可以快速的部署harbor。(在GitHub首页搜索harbor,在结果页面点Releases,可以选择版本)。下载传至主机目录/data/install/harbor
安装docker-compose
搜索网上文章可知
安装harbor
mkdir /data/install -p
cd /data/install
tar zxvf harbor-offline-installer-v2.3.1.tgz
cd harbor
vim harbor.yml
##harbor.yml begin(修改部分)####
hostname: k8s-node1 #修改hostname
ui_url_protocol: https #新增行
...
https:
# https port for harbor, default is 443
port: 1443 #修改端口号为1443
# The path of cert and key files for nginx
certificate: /data/cert/k8s-node1.pem #修改文件路径
private_key: /data/cert/k8s-node1key #修改文件路径
####### harbor.yml end ##########
###修改docker-compose.yml begin######
......
networks:
- harbor
dns_search: .
ports:
- 80:8080
- 1443:8443 #修改443为1443
......
###修改docker-compose.yml end######
[root@k8s-node1 /data/install/harbor/]#./prepare
[root@k8s-node1 /data/install/harbor/]#./install.sh
......
看到下面内容,说明安装成功:
[Step 5]: starting Harbor ...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating registryctl ... done
Creating harbor-db ... done
Creating redis ... done
Creating registry ... done
Creating harbor-portal ... done
Creating harbor-core ... done
Creating harbor-jobservice ... done
Creating nginx ... done
✔ ----Harbor has been installed and started successfully.----
docker-compose up -d # 后台启动,如果容器不存在根据镜像自动创建
docker-compose down -v # 停止容器并删除容器
docker-compose start # 启动容器,容器不存在就无法启动,不会自动创建镜像
docker-compose stop # 停止容器
内网访问内网访问harbor的时候走的是http,所以IP写的是内网IP访问主机需要修改 /etc/docker/daemon.json
[root@k8s-master ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"], #换行的逗号别忘了
"insecure-registries": ["172.31.0.25","k8s-node1"] #新增
}
重启docker
[root@k8s-master ~]# systemctl daemon-reload && systemctl restart docker
[root@k8s-master ~]#docker login 172.31.0.25
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@k8s-master ~]# docker tag busybox 172.31.0.25/test/busybox:v1
[root@k8s-master ~]# docker push 172.31.0.25/test/busybox:v1
The push refers to repository [172.31.0.25/test/busybox]
0fd05bf2930d: Pushed
v1: digest: sha256:b862520da7361ea093806d292ce355188ae83f21e8e3b2a3ce4dbdba0a230f83 size: 527
[root@k8s-master ~]# docker rmi 172.31.0.25/test/busybox:v1
Untagged: 172.31.0.25/test/busybox:v1
Untagged: 172.31.0.25/test/busybox@sha256:b862520da7361ea093806d292ce355188ae83f21e8e3b2a3ce4dbdba0a230f83
[root@k8s-master ~]# docker images |grep busybox
busybox latest 42b97d3c2ae9 3 months ago 1.24MB
[root@k8s-master ~]# docker pull 172.31.0.25/test/busybox:v1
v1: Pulling from test/busybox
Digest: sha256:b862520da7361ea093806d292ce355188ae83f21e8e3b2a3ce4dbdba0a230f83
Status: Downloaded newer image for 172.31.0.25/test/busybox:v1
172.31.0.25/test/busybox:v1
[root@k8s-master ~]# docker images |grep busybox
172.31.0.25/test/busybox v1 42b97d3c2ae9 3 months ago 1.24MB
busybox latest 42b97d3c2ae9 3 months ago 1.24MB
[root@k8s-
一般使用systemctl status docker 和 journalctl -u docker.service
[root@k8s-master ~]# systemctl restart docker
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
[root@k8s-master ~]# systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: failed (Result: start-limit) since Mon 2021-10-11 21:54:50 CST; 5min ago
Docs: https://docs.docker.com
Process: 30461 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=1/FAILURE)
Main PID: 30461 (code=exited, status=1/FAILURE)
Oct 11 21:54:48 k8s-master systemd[1]: docker.service failed.
Oct 11 21:54:50 k8s-master systemd[1]: docker.service holdoff time over, scheduling restart.
Oct 11 21:54:50 k8s-master systemd[1]: Stopped Docker Application Container Engine.
Oct 11 21:54:50 k8s-master systemd[1]: start request repeated too quickly for docker.service
Oct 11 21:54:50 k8s-master systemd[1]: Failed to start Docker Application Container Engine.
Oct 11 21:54:50 k8s-master systemd[1]: Unit docker.service entered failed state.
Oct 11 21:54:50 k8s-master systemd[1]: docker.service failed.
Oct 11 21:54:50 k8s-master systemd[1]: start request repeated too quickly for docker.service
Oct 11 21:54:50 k8s-master systemd[1]: Failed to start Docker Application Container Engine.
Oct 11 21:54:50 k8s-master systemd[1]: docker.service failed.
[root@k8s-master ~]# journalctl -u docker.service
-- Logs begin at Mon 2021-10-11 09:49:18 CST, end at Mon 2021-10-11 21:55:56 CST. --
Oct 11 21:15:15 k8s-master systemd[1]: Starting Docker Application Container Engine...
Oct 11 21:15:15 k8s-master dockerd[16812]: unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '"' after object key:value pair
Oct 11 21:15:15 k8s-master systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE
Oct 11 21:15:15 k8s-master systemd[1]: Failed to start Docker Application Container Engine.
Oct 11 21:15:15 k8s-master systemd[1]: Unit docker.service entered failed state.
Oct 11 21:15:15 k8s-master systemd[1]: docker.service failed.
Oct 11 21:15:18 k8s-master systemd[1]: docker.service holdoff time over, scheduling restart.
Oct 11 21:15:18 k8s-master systemd[1]: Stopped Docker Application Container Engine.
Oct 11 21:15:18 k8s-master systemd[1]: Starting Docker Application Container Engine...
Oct 11 21:15:18 k8s-master dockerd[16820]: unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '"' after object key:value pair
#可以看到docker 无法启动是因为/etc/docker/daemon.json里有无法识别的字符,原因是文件换行之间漏掉了逗号,
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
"insecure-registries": ["172.31.0.25:5000"]
}