项目打包为docker镜像并上传到本地私有仓库

前提以python项目为例

centos服务安装了docker
docker安装python, 本人用python3.6.4版本

1、首先将pip输出为文件

pip freeze > requirements.txt # 输出本地包环境至文件

2、建一个Dockerfile文件放到根目录下

文件填写以下内容

#基于的父基础镜像
FROM python:3.6.4
# 维护者
MAINTAINER [email protected]

# 环境设置
ENV PATH /user/local/bin:$PATH

# 创建code文件夹
RUN mkdir /code

#转移项目
ADD . /code
#
切换为工作文件
WORKDIR /code

#安装项目依赖包
RUN pip install --upgrade pip
RUN pip3 install -r requirements.txt -i https://pypi.douban.com/simple --trusted-host pypi.douban.com

#暴露端口
EXPOSE 8000

#启动项目
CMD ["python", "/code/run.py"]

dockerfle的命令参数

FROM:指定基础镜像,必须为第一个命

格式:
  FROM <image>
  FROM <image>:<tag>
  FROM <image>@<digest>
示例:
  FROM mysql:5.6
注:
  tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜

MAINTAINER: 维护者信息

格式:
    MAINTAINER <name>

RUN:构建镜像时执行的命令

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:
  RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式:
    ADD <src>... <dest>
    ADD ["",... ""] 用于支持包含空格的路径

COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
CMD:构建容器后调用,也就是在容器启动时才进行调用。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
注:
   CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去"application",只使用参数

格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)

注:
   ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。

LABEL:用于为镜像添加元数据

格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

ENV:设置环境变量

格式:
    ENV <key> <value>  #之后的所有内容均会被视为其的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"="的键值对,如果中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
注:
	两者的区别就是第一种是一次设置一个,第二种是一次设置多个

EXPOSE:指定于外界交互的端口

格式:
    EXPOSE <port>/<tcp/udp>
注:
  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

VOLUME:可实现挂载功能,可以将宿主机目录挂载到容器中

格式:
    VOLUME ["path"]
注:
  一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

卷可以容器间共享和重用
容器并不一定要和其它容器共享卷
修改卷后会立即生效
对卷的修改不会对镜像产生影响
卷会一直存在,直到没有任何容器在使用它

USER设置启动容器的用户,可以是用户名或UID

格式:
	USER daemo
	USER UID
注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

ARG:用于指定传递给构建运行时的变量

格式:
    ARG <name>[=<default value>]
注:
	设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg =来指定参数
	如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning

ONBUILD:用于设置镜像触发器

格式:
  ONBUILD [INSTRUCTION]
注:
  当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

WORKDIR设置工作目录

格式:
    WORKDIR /path
注:
	,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。

STOPSIGNAL命令是的作用是当容器停止时给系统发送什么样的指令,默认是15
HEALTHCHECK容器健康状况检查命令

格式:
	 HEALTHCHECK [OPTIONS] CMD command
	 HEALTHCHECK NONE
注:
	第一个的功能是在容器内部运行一个命令来检查容器的健康状况
	第二个的功能是在基础镜像中取消健康检查命令

[OPTIONS]的选项支持以下三中选项:
–interval=DURATION 两次检查默认的时间间隔为30秒
–timeout=DURATION 健康检查命令运行超时时长,默认30秒
–retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3
注意: HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:
0: success - 表示容器是健康的
1: unhealthy - 表示容器已经不能工作了
2: reserved - 保留值
项目打包为docker镜像并上传到本地私有仓库_第1张图片

3、创建本地镜像

将文件传到linux服务上
在linux服务切换到上传的文件夹下,
输入docker命令 webapi 是自己随意起的 .
表示运行该目录的Dockerfile

docker build -t webapi .

4、笔者创建镜像遇到的错误

4.1、安装环境最大的问题内存不足

错误类型: no space left on device (磁盘空间不足)
解决方法: 删除无用的镜像

4.2、安装docker拉取python镜像报错 docker pull python:3.6.4

错误类型:
error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/07/07d72c0beb9900745bd421e4aa8d935550fb427a28035b2230d9d68ea343ac25/data?verify=1594977379-Uk1xjHWcsk3rq5TiPorL3tkR0nw%3D: dial tcp 104.18.123.25:443: i/o timeout
解决方法:
修改docker国内镜像
创建或修改 /etc/docker/daemon.json 文件,修改为如下形式

{
     
    "registry-mirrors": ["http://hub-mirror.c.163.com"]
}

systemctl restart docker 重启docker

4.3、运行创建镜像命令到安装项目依赖包pip insatll时总会安装时间超时报错,导致无法生成镜像

错误类型: Retrying (Retry(total=4, connect=None, read=None, redirect=None,
status=None)) after connection broken by 'ConnectTimeoutError 解决方法:
1、将requirements.txt文件的依赖包删除掉,只保留主要的,如该框架的fastapi,uvicorn,mysql-connector-python,SQLAlchemy,pymysql
2、加上国内环境源,如Dockerfile的【-i https://pypi.douban.com/simple
–trusted-host pypi.douban.com】使用的是豆瓣的环境源

5、搭建私有仓库

5.1、 下载registry镜像

docker pull registry

5.2、 配置Docker启动参数

因为Docker从1.3.X之后,与docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报下面的错误

The push refers to repository [ip:5000/busybox] Error: Get
https://ip/v2/: http: server gave HTTP response to HTTPS client

5.2.1、其他服务器给docker注册https协议,支持https访问

vim /etc/docker/daemon.json
如果daemon文件不存在,vim会自己创建一个,添加一下代码,
  {
     
      "insecure-registries":["主机的IP地址或者域名:5000"],
      "registry-mirrors": ["https://registry.docker-cn.com"]
  }
注释:
  insecure-registries----->开放注册https协议
  registry-mirrors----->仓库源

重启docker服务   service docker restart  

5.2.2、给本地服务docker注册https协议,支持https访问

为了解决本地私有仓库报错需要在启动docker server时增加启动参数为默认使用http访问。修改docker启动配置文件:
vim  /usr/lib/systemd/system/docker.service 
找到 ExecStart=/usr/bin/dockerd 后边添加
ExecStart=/usr/bin/dockerd  --insecure-registry 本地ip:5000
重启docker:
systemctl daemon-reload
systemctl restart docker

5.3、启动镜像服务器registry

首先在在主机上新建一个目录,供存储镜像

mkdir -p /data/registry/

创建配置文件/data/registry-config.yml,内容如下:

storage.delete.enabled=true设置镜像可删除

version: 0.1
log:
  fields:
    service: registry
storage:
    delete:
        enabled: true
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
http:
    addr: :5000
    headers:
        X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s

启动镜像

docker run -d -p 5000:5000 --restart=always --privileged=true -v /data/registry-config.yml:/etc/docker/registry/config.yml -v /data/registry:/var/lib/registry --name docker-registry registry

解释:
  -p 5000:5000 端口
  --name=docker-registry 运行的容器名称
  --restart=always 设置重启策略,这里设置为退出后自动重启
  --privileged=true centos7中的安全模块selinux把权限禁止了,加上这行是给容器增加执行权限
-v /data/registry-config.yml:/etc/docker/registry/config.yml 挂载配置文件
  -v /data/registry:/var/lib/registry 把主机的/data/registry 目录挂载到registry容器的/var/lib/registry目录下,假如有删除容器操作,我们的镜像也不会被删除
  registry  镜像名称

5.44、上传本地镜像

修改一下该镜像的tag。

docker tag webapi 本地ip:5000/webapi

上传镜像到私有registry

docker push 本地ip:5000/webapi

在私有registry上查看镜像

curl http://本地ip:5000/v2/_catalog
——————————————————
{“repositories”:[“webapi”]}

5.5其他服务部署镜像(区域网格,外网没试过)

从私有registry上下载镜像
删除本地镜像

docker rmi 本地ip:5000/webapi

从私有registry上下载

docker pull 本地ip:5000/webapi

查看本地镜像,可以看到已经拉下来了。

docker images

5.6 查看私有镜像进行操作

5.6.1、查看有什么镜像

curl -XGET http://本地ip:5000/v2/_catalog

5.6.2、镜像查看版本

curl -GET http://本地ip:5000/v2/镜像名称/tags/list

5.6.3、查询镜像digest_hash

curl --header “Accept:application/vnd.docker.distribution.manifest.v2+json” -I -XGET http://本地ip:5000/v2/<镜像名>/manifests/

5.6.4、删除镜像digest_hash

curl -I -X DELETE
“http://本地ip:5000/v2/<镜像名>/manifests/<镜像digest_hash>”

5.6.5、因为docker删除p_w_picpath只是删除的p_w_picpath的元数据信息。层数据并没有删除。现在进入registry中进行垃圾回收

进入registry容器
docker exec -it 071105c54db3 /bin/sh
查看镜像大小
du -chs /var/lib/registry/
执行回收命令
registry garbage-collect /etc/docker/registry/config.yml
再次查询,发现回收资源执行成功
du -chs /var/lib/registry/

5.7、将本地镜像打包成tar文件,保存到/tmp/目录下

docker save -o /tmp/webapi.tar 本地ip:5000/webapi

参数说明:
save:将指定镜像保存成tar归档文件
-o:目标文件,可使用绝对路径和相对路径

你可能感兴趣的:(知识,linux,centos,容器)