Docker Image & Docker Hub

华欣荣
2023-12-01

构建Docker镜像

参考官方文档:Dockerfile

构建Docker镜像是使用的Dockerfile,然后把所有的依赖包放到Dockerfile的同级目录。

为什么需要都放到当前目录?
因为docker build的第一个步骤就是将此次构建的工作目录发给docker daemon。

Dockerfile类似机器码,一个命令是一行,分成几类。

向镜像中添加文件

COPY和ADD

比如ADD jdk-11.0.7 /opt/sonar/jdk,就是将当前目录下jdk-11.0.7的全部内容放到/opt/sonar/jdk目录下,目录如果不存在,会自动建。

COPY和ADD的主要区别就是ADD多了个功能就是可以从远程下载文件放到docker镜像里。这在自动化构建时,比如你的程序包是放在远程文件系统中时,是比较有用的。

特殊用法:

FROM golang:1.17.6
# 容器工作目录
WORKDIR /go/src/sigs.k8s.io/scheduler-plugins
# 这里的copy . .的意思是拷贝当前工作目录(Dockerfile所在的目录)到容器工作目录(WORKDIR)
COPY . .
ARG ARCH
RUN make build-controller.$ARCH

注入环境变量

ARG和ENV

ENV hello world
ENV hello=world

容器中运行的应用可以通过环境变量获取到ENV定义的值。Docker引入这个特殊的命令,就是为了规范环境变量向容器的注入。不要把环境变量放到/etc/profile

ARG和ENV的区别?作用域不同,ARG只能Dockerfile里使用(构建时),ENV除了可以在构建时,也可以被运行时容器当作系统环境变量读到。

如何引用ENV变量?

我构建JDK镜像包时,发现PATH变量可以引用构建镜像的当前宿主机的PATH变量。

像下面这样使用行内替换语法:

# 这里${PATH}引用宿主机的PATH变量,这种引用叫inline replacement	
ENV PATH=${PATH}:/opt/sonar/sonar/bin/linux-x86-64

执行Shell脚本

两种语法格式,RUN命令可以有多个。

# bash -c
RUN chown -R sonar:sonar /opt/sonar
# json格式
RUN ["echo","hello"]

切换用户

有些应用程序不能以root运行,docker默认用户是root。要更改用户:

# 切换到用户sonar
USER sonar
# 之后的命令都是以sonar用户权限运行
RUN whoami

追加/etc/hosts文件

docker CLI

或者使用docker run的–add-host指令

--add-host=""      : Add a line to /etc/hosts (host:IP)

docker-compose

docker-compose.yaml

services:
  service-a:
    environment:
    - DEBUG=1
    extra_hosts:
    - test.gitlab.com:192.168.10.8

容器启动命令

CMD和ENTRYPOINT

我认为没必要搞出这两个语法,有啥意义呢?都是一样的。ENTRYPOINT是JSON格式的语法。

# json格式
ENTRYPOINT ["echo","hello"]

一个Dockerfile里写一个ENTRYPOINT就可以了。不要写多个,否则会覆盖

长期运行的容器需要这种命令。不过难受的是,你的命令如果是后台运行,容器启动就闪退了。这是因为容器中后台运行的应用没有阻塞,进程正常终止的返回值为0。

实战: sonarqube镜像构建

sonarqube是一个web应用,用于代码分析。其使用JDK-11,以非root用户运行。

# 以Centos 7.5为基础镜像
FROM centos:centos7.5.1804
MAINTAINER oneslide
# 镜像元信息,可以忽略
LABEL os.version="centos"
LABEL build.date="2020-07-07"
LABEL who.build.this="oneslide"
# 创建一个非root用户sonar
RUN useradd sonar -d /opt/sonar -s /sbin/nologin
# jdk11复制到/opt/sonar/jdk
ADD jdk-11.0.7 /opt/sonar/jdk
# 配置java环境变量
ENV JAVA_HOME /opt/sonar/jdk
ENV PATH=${PATH}:${JAVA_HOME}/bin
# 添加sonarqube(web应用)的包
ADD sonarqube-8.3.1.34397 /opt/sonar/sonar
# 设置当前工作目录,意味着ls会列出/opt/sonar文件夹下的文件
WORKDIR /opt/sonar
# 再次设置环境变量,因为web应用的启动脚本需要放在PATH下
ENV PATH=${PATH}:/opt/sonar/sonar/bin/linux-x86-64
RUN chown -R sonar:sonar /opt/sonar 
# 以sonar用户运行
USER sonar
# 暴露web应用的端口(容器端口),这个不是随便写的,你的应用监听哪个端口,就写哪个
EXPOSE 9000
# 后台启动web,并一直查看日志
CMD sonar.sh start && tail -f sonar/logs/sonar.log

然后我的目录结构是这样的:

[root@oneslide jdk11-centos]# tree -L 1
.
├── Dockerfile
├── jdk-11.0.7
├── jdk-11.0.7_linux-x64_bin.tar.gz
├── sonarqube-8.3.1.34397
├── sonarqube-8.3.1.34397.zip
└── sonarqube8.tar

构建镜像:

# .代表当前目录,-t是镜像的tag,格式是name:version
docker build -t sonarqube:1.0v .

Docker Automated Build 持续集成与虚拟化

Docker镜像上传到Dockerhub的方式,分为手动和自动。

手动方式是本地构建好了docker镜像之后,使用docker push命令推送到dockerhub;

自动方式是让Dockerhub监听Github远程仓库的变更,自动构建Docker镜像并推
送。

将本地镜像上传到DockerHub

# 复制本地镜像local-image:tagname,并将标签重贴为new-repo:tagname
docker tag local-image:tagname new-repo:tagname
# 推送到Registry
docker push new-repo:tagname
 类似资料:

相关阅读

相关文章

相关问答