阿里云搭建docker私有镜像仓库与SpringBoot项目推送远程镜像仓库

1. 前言

随着项目上容器技术的广泛应用,我也加入了Docker容器技术的学习。首先初学Docker,我的想法很简单。创建一个SpringBoot项目,如何将SpringBoot项目打包成容器镜像,然后推送至远程的Docker服务上部署。带着这个目的查阅了一些资料后,整体的实现思路如下:

  • 构建一个Docker的私有镜像仓库,用于存储Docker镜像,当需要启动容器服务时可以指定Docker去私有镜像仓库获取镜像;
  • SpringBoot在打包的时候,使用插件对镜像进行打包并推送到远程的Docker镜像仓库;
  • Docker启动容器时指定获取镜像的仓库。

环境描述:
准备一台阿里云服务器,已经完成Docker服务安装,后续将会在该服务器上进行搭建Docker私有镜像仓库。本地准备一个SpringBoot项目,至少编写一个Controller,保证本地SpringBoot项目启动后能够正常访问到Contriller。

2. 搭建建Docker私有镜像仓库

  • 修改配置
    registry-mirrors: 配置的是阿里云镜像加速地址,此项配置不是搭建私有仓库必须的。
    insecure-registries: 此项配置是让Docker信任私有仓库地址,xx.96.194.xx为服务器的IP,2112为私有仓库的端口。
# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"],
  "insecure-registries": ["xx.96.194.xx:2112"]
}
  • 拉取私有仓库镜像
docker pull registry
  • 重新加载配置信息,重启Docker服务
# 重新加载某个服务的配置文件
sudo systemctl daemon-reload
# 重新启动 docker
sudo systemctl restart docker

3. 创建私有仓库并配置认证

由于私有镜像仓库是部署在阿里云上,要确保私有仓库的安全性,需要一个安全认证证书,防止发生意想不到的事情。所有需要在搭建私有仓库的Docker主机上先生成自签名证书。

  • 创建证书存储目录
mkdir -p /usr/local/registry/certs
  • 生成自签名证书命令
openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/registry/certs/domain.key -x509 -days 365 -out /usr/local/registry/certs/domain.crt
  1. openssl req:创建证书签名请求等功能;
  2. -newkey: 创建 CSR 证书签名文件和 RSA 私钥文件;
  3. rsa:2048:指定创建的 RSA 私钥长度为 2048;
  4. -nodes:对私钥不进行加密;
  5. -sha256:使用 SHA256 算法;
  6. -keyout:创建的私钥文件名称及位置;
  7. -x509:自签发证书格式;
  8. -days:证书有效期;
  9. -out:指定 CSR 输出文件名称及位置;

生成自签名证书:
通过openssl命令先生成自签名证书,运行命令后需要填写一些证书信息。其中Common Name填写的xx.96.104.xxx是最关键的信息,这里填写的是私有仓库的地址:
Country Name:国家
State or Province Name:州或省
Locality Name:城市
Organization Name :机构名称
Organizational Unit Name :组织单位名称
Common Name:hostname域名
Email Address:邮箱地址

[root@iZ2ze0r5hel5o6fik77a26Z ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/registry/certs/domain.key -x509 -days 365 -out /usr/local/registry/certs/domain.crt
Generating a 2048 bit RSA private key
..............+++
............................+++
writing new private key to '/usr/local/registry/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) []:BJ
Locality Name (eg, city) [Default City]:BJ
Organization Name (eg, company) [Default Company Ltd]:docker
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:xx.96.104.xxx
Email Address []:xxxxx@163.com
  • 生成鉴权密码文件
    htpasswd 是 apache http 的基本认证文件,使用 htpasswd 命令可以生成用户及密码文件:
# 创建存储鉴权密码文件目录
mkdir -p /usr/local/registry/auth
# 如果没有 htpasswd 功能需要安装 httpd
yum install -y httpd
# 创建用户和密码
htpasswd -Bbn root ***1234 > /usr/local/registry/auth/htpasswd
  • 创建私有仓库容器
  1. -d:后台运行容器;
  2. --name:为创建的容器命名;
  3. -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射;
  4. -v:将容器内 /var/lib/registry 目录下的数据挂载至宿主机 /mydata/docker_registry 目录下;
docker run -di --name registry -p 2112:5000 \
   -v /mydata/docker_registry:/var/lib/registry \
   -v /usr/local/registry/certs:/certs \
   -v /usr/local/registry/auth:/auth \
   -e "REGISTRY_AUTH=htpasswd" \
   -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
   -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
   -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
   -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
   registry

4. 操作私有容器镜像仓库

  1. 首先通过 docker login 命令输入账号密码登录私有仓库
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker login xx.96.194.xx:2112
Username: root
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
  1. 推送镜像至私有仓库
    先给镜像设置标签 docker tag local-image:tagname new-repo:tagname
    再将镜像推送至私有仓库 docker push new-repo:tagname
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker tag hello-world:latest xx.96.194.xx:2112/test-hello-world:1.0.0
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker push xx.96.194.xx/test-hello-world:1.0.0
The push refers to repository [xx.96.194.xx/test-hello-world]
An image does not exist locally with the tag: xx.96.194.xx/test-hello-world
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# 
  1. 查看推送至私有仓库的镜像
    由于我们做了目录挂载,因此可以在宿主机 /mydata/docker_registry/docker/registry/v2/repositories 目录下查看。
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# ll /mydata/docker_registry/docker/registry/v2/repositories/
total 8
drwxr-xr-x 5 root root 4096 Dec 15 10:04 actual-combat
drwxr-xr-x 5 root root 4096 Dec 14 12:36 test-hello-world
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# 
  1. 退出docker账号
    所有的推送镜像操作完成后,可以使用docker logout 命令退出账号。
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker logout xx.96.194.xx
Removing login credentials for xx.96.194.xx
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# 

5.搭建SpringBoot工程

  • 创建一个Controller
@Slf4j
@RestController
@RequestMapping(value = "user")
public class UserController {

    @RequestMapping(value = "/info")
    @ResponseBody
    public String getUser() {
        User user = new User();
        user.setUserName("张三");
        user.setPassword("qwertyuiop");
        return JSONObject.toJSONString(user);
    }
}
  • 启动SpringBoot工程保证Controller能够正常访问


    获取用户信息

6. SpringBoot项目集成镜像打包插件

  • pom文件引入jib-maven-plugin插件依赖
        <dependency>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>jib-maven-plugin</artifactId>
            <version>2.8.0</version>
        </dependency>
  • pom文件编写jib镜像打包plugin
        <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>2.8.0</version>
                <configuration>
                    <!-- 拉取所需的基础镜像 -->
                    <from>
                        <!-- 默认从官方公共仓库拉取镜像,速度较慢 -->
                        <image>openjdk:alpine</image>
                        <!-- 从指定仓库拉取镜像提速(需提前将镜像 push 至仓库) -->
                        <!--<image>192.168.10.10:5000/openjdk:alpine</image>-->
                    </from>
                    <!-- push 到哪个镜像仓库(公共仓库、阿里云仓库、私有自建仓库等) -->
                    <to>
                        <!-- 使用 DockerHub 的官方公共仓库:仓库地址/用户名/镜像名 -->
                        <!--<image>registry.hub.docker.com/mrhelloworld/${project.name}</image>-->
                        <!-- 使用自建的私有仓库:仓库地址/镜像名 -->
                        <image>xx.96.194.xx:2112/${project.artifactId}</image>
                        <!-- 镜像版本号 -->
                        <tags>
                            <tag>${project.version}</tag>
                        </tags>
                        <!-- 连接仓库的账号密码 -->
                        <auth>
                            <username>root</username>
                            <password>xxxxxx</password>
                        </auth>
                    </to>
                    <!-- 使 jib 插件支持 http 协议连接镜像仓库(安全起见,默认是关闭的) -->
                    <allowInsecureRegistries>true</allowInsecureRegistries>
                    <container>
                        <!-- 启动类 -->
                        <mainClass>com.erxiao.actualCombat.ActualCombatApplication</mainClass>
                    </container>
                </configuration>
            </plugin>
  • 打开Terminal执行打包命令
    jib:build命令会完成镜像打包,并推送到远程仓库。
 mvn install -Dmaven.test.skip=true
 mvn compile jib:build -Dmaven.test.skip=true

7. 查看并启动镜像

  • 查看镜像
    查看镜像有两个方式,方式一,使用curl命令连接docker私有仓库查看。方式二,安装registry-web通过Web UI界面查看。
  1. 使用curl命令
    curl -kiv -H "Authorization: Basic $(echo -n "root:wangxxxx" | base64)" https://localhost:2112/v2/_catalog 其中root:wangxxxx为关键信息,对应着生成鉴权密码文件时,用htpasswd 命令生成的用户与密码,用户名与密码直接使用英文冒号分隔。返回的{"repositories":["actual-combat","test-hello-world"]}内容就是当前私有仓库中的镜像。
# curl -kiv -H "Authorization: Basic $(echo -n "root:wangxxxx" | base64)" https://localhost:2112/v2/_catalog
* About to connect() to localhost port 2112 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 2112 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*       subject: E=xxxxxxxx_email@sina.com,CN=xx.96.194.xxx,OU=erxiao,O=erxiao,L=BJ,ST=BJ,C=CN
*       start date: Dec 14 04:42:52 2021 GMT
*       expire date: Dec 14 04:42:52 2022 GMT
*       common name: xx.96.194.xxx
*       issuer: E=xxxxxx_email@sina.com,CN=xx.96.194.xxx,OU=erxiao,O=erxiao,L=BJ,ST=BJ,C=CN
> GET /v2/_catalog HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2112
> Accept: */*
> Authorization: Basic cm9vdDp3YW5nY29uZw==
> 
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
Content-Type: application/json; charset=utf-8
< Docker-Distribution-Api-Version: registry/2.0
Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< Date: Sat, 18 Dec 2021 12:53:12 GMT
Date: Sat, 18 Dec 2021 12:53:12 GMT
< Content-Length: 54
Content-Length: 54

< 
{"repositories":["actual-combat","test-hello-world"]}
* Connection #0 to host localhost left intact
  1. 安装registry-web通过页面查看镜像
    参数解释:
    -p 7001:8080 host主机端口8080映射到container8080
    --name 起个名字,docker logs start stop时就可以用了
    --link 连接registry,可以不加,以为下面有registry的url访问方式(registry必须和与私有镜像仓库保持一致)
    -e REGISTRY_TRUST_ANY_SSL=true, 环境变量,相信所有的ssl,因为我们大部分的ssl都是自建的
    -e REGISTRY_BASEIC_AUTH 这个里面的值是账号以及密码的base64获取的,可以通过
    echo "ops:123123123" | base64
    b3BzOjEyMzEyMzEyMwo=
    获得。
    -e REGISTRY_NAME, 目前看起来这个是会在页面上的显示
docker run -itd -p 7001:8080 --name registry-web --link registry \
           -e REGISTRY_URL=https://xx.96.194.xxx:2112/v2 \
           -e REGISTRY_TRUST_ANY_SSL=true \
           -e REGISTRY_BASIC_AUTH="cm9vdDp3YW5nY29uZw==" \
           -e REGISTRY_NAME=docker_registry hyper/docker-registry-web

页面访问:
页面访问:http://xx.96.194.xxx:7001/

仓库镜像列表

  • 启动镜像
    docker run -di --name actual-combat -p 7000:8080 xx.96.194.xxx:2112/actual-combat:latest
    --name指定镜像名称
    actual-combat:latest需要和私有镜像仓库中的镜像保持一致
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker run -di --name actual-combat -p 7000:8080 xx.96.194.xxx:2112/actual-combat:latest
12f8cf18723fed54e17702659929e538cf8a878802a0820eeb46996962543e61
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# 

页面访问Spring Boot项目

页面访问

8. 常用命令

  • 获取当前运行的镜像
    docker ps
# docker ps
CONTAINER ID   IMAGE                                     COMMAND                  CREATED             STATUS             PORTS                    NAMES
12f8cf18723f   xx.96.194.xxx:2112/actual-combat:latest   "java -cp /app/resou…"   17 minutes ago      Up 17 minutes      0.0.0.0:7000->8080/tcp   actual-combat
59d00326d2b7   hyper/docker-registry-web                 "start.sh"               About an hour ago   Up About an hour   0.0.0.0:7001->8080/tcp   registry-web
4c0fd415f702   registry                                  "/entrypoint.sh /etc…"   4 days ago          Up 4 days          0.0.0.0:2112->5000/tcp   registry
  • 停止镜像
    docker stop [CONTAINER ID]
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker stop 8de8c650c485
8de8c650c485
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# 
  • 删除镜像
    docker rm [CONTAINER ID]
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker rm 8de8c650c485
8de8c650c485
[root@iz2zeh3bjq6rgoli6ng5g9z ~]#
  • 查看容器日志
    docker logs -f [CONTAINER ID]
[root@iz2zeh3bjq6rgoli6ng5g9z ~]# docker logs -f 59d00326d2b7
CATALINA_OPTS: -Djava.security.egd=file:/dev/./urandom -Dcontext.path=
Using CATALINA_BASE:   /var/lib/tomcat7
Using CATALINA_HOME:   /usr/share/tomcat7
Using CATALINA_TMPDIR: /var/lib/tomcat7/temp
Using JRE_HOME:        /usr/lib/jvm/java-7-openjdk-amd64
Using CLASSPATH:       /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar
Dec 18, 2021 1:02:07 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]

参考:Docker 私有镜像仓库的搭建及认证
参考:Spring Boot 多样化构建 Docker 镜像
参考:registry-web集成安全认证

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容