Dockerfile实战学习

21 篇文章 0 订阅

Dockerfile指南:

事情:nginx。tomcat。mysql。镜像从哪里来?

我们自己如何做一个镜像。微服务。SpringBoot。上云部署。最方便是Docker。

微服务打包成镜像。任何装了Docker。都可以下载使用。

应用–>Dockerfile—>打包成镜像—>上传到仓库(公有仓库,私有仓库)—>下载镜像—>启动运行。

移植:扩充服务器。

如何得到一个镜像

1、自己做的Dockefile

#nginx Dockerfile的示例
#alpine:3.11超迷你的linux 4mb;
#alpine:3.11 linux全目录 基于宿主机linux的一个统一接口。cpu,mem。主机。
FROM alpine:3.11

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"

#环境
ENV NGINX_VERSION 1.18.0
ENV NJS_VERSION   0.4.0
ENV PKG_RELEASE   1

RUN set -x \
# create nginx user/group first, to be consistent throughout docker variants
    && addgroup -g 101 -S nginx \
    && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
    && apkArch="$(cat /etc/apk/arch)" \
    && nginxPackages=" \
        nginx=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-xslt=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-geoip=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-image-filter=${NGINX_VERSION}-r${PKG_RELEASE} \
        nginx-module-njs=${NGINX_VERSION}.${NJS_VERSION}-r${PKG_RELEASE} \
    " \
    && case "$apkArch" in \
        x86_64) \
# arches officially built by upstream
            set -x \
            && KEY_SHA512="e7fa8303923d9b95db37a77ad46c68fd4755ff935d0a534d26eba83de193c76166c68bfe7f65471bf8881004ef4aa6df3e34689c305662750c0172fca5d8552a *stdin" \
            && apk add --no-cache --virtual .cert-deps \
                openssl \
            && wget -O /tmp/nginx_signing.rsa.pub https://nginx.org/keys/nginx_signing.rsa.pub \
            && if [ "$(openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -text -noout | openssl sha512 -r)" = "$KEY_SHA512" ]; then \
                echo "key verification succeeded!"; \
                mv /tmp/nginx_signing.rsa.pub /etc/apk/keys/; \
            else \
                echo "key verification failed!"; \
                exit 1; \
            fi \
            && apk del .cert-deps \
            && apk add -X "https://nginx.org/packages/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \
            ;; \
        *) \
# we're on an architecture upstream doesn't officially build for
# let's build binaries from the published packaging sources
            set -x \
            && tempDir="$(mktemp -d)" \
            && chown nobody:nobody $tempDir \
            && apk add --no-cache --virtual .build-deps \
                gcc \
                libc-dev \
                make \
                openssl-dev \
                pcre-dev \
                zlib-dev \
                linux-headers \
                libxslt-dev \
                gd-dev \
                geoip-dev \
                perl-dev \
                libedit-dev \
                mercurial \
                bash \
                alpine-sdk \
                findutils \
            && su nobody -s /bin/sh -c " \
                export HOME=${tempDir} \
                && cd ${tempDir} \
                && hg clone https://hg.nginx.org/pkg-oss \
                && cd pkg-oss \
                && hg up -r 474 \
                && cd alpine \
                && make all \
                && apk index -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \
                && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \
                " \
            && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \
            && apk del .build-deps \
            && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \
            ;; \
    esac \
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
    && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \
    && if [ -n "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi \
    && if [ -n "/etc/apk/keys/nginx_signing.rsa.pub" ]; then rm -f /etc/apk/keys/nginx_signing.rsa.pub; fi \
# Bring in gettext so we can get `envsubst`, then throw
# the rest away. To do this, we need to install `gettext`
# then move `envsubst` out of the way so `gettext` can
# be deleted completely, then move `envsubst` back.
    && apk add --no-cache --virtual .gettext gettext \
    && mv /usr/bin/envsubst /tmp/ \
    \
    && runDeps="$( \
        scanelf --needed --nobanner /tmp/envsubst \
            | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
            | sort -u \
            | xargs -r apk info --installed \
            | sort -u \
    )" \
    && apk add --no-cache $runDeps \
    && apk del .gettext \
    && mv /tmp/envsubst /usr/local/bin/ \
# Bring in tzdata so users could set the timezones through the environment
# variables
    && apk add --no-cache tzdata \
# Bring in curl and ca-certificates to make registering on DNS SD easier
    && apk add --no-cache curl ca-certificates \
# forward request and error logs to docker log collector
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log \
# make default server listen on ipv6
    && sed -i -E 's,listen       80;,listen       80;\n    listen  [::]:80;,' \
        /etc/nginx/conf.d/default.conf

EXPOSE 80

STOPSIGNAL SIGTERM

CMD ["nginx", "-g", "daemon off;"]
# Dockerfile复原了我们在linux上安装nginx的过程。

XXX给我们准备好的文件。xxx.tar。可以通过硬盘传输使用。

在这里插入图片描述

2、上传项目到服务器。

3、进入项目,构建镜像到本地仓库;

- `docker build -t nginx:1.0 -f ./Dockerfile .`  别忘了最后的小数点。
- docker images 查看镜像
- docker exec -it 容器id /bin/bash;进入容器,修改容器
- docker commit -a “icoding” -m “nginxxx” 容器id mynginx:2.0
  - docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  - OPTIONS说明:
    - -a :提交的镜像作者;
    - -c :使用Dockerfile指令来创建镜像;
    - -m :提交时的说明文字;
    - -p :在commit时,将容器暂停。
- docker login : 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
  - docker login -u 用户名 -p 密码
- docker logout : 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub

4、推送镜像到docker hub

- 标记镜像,docker tag local-image:tagname username/new-repo:tagname
- 上传镜像,docker push username/new-repo:tagname 

5、保存镜像,加载镜像

- 可以保存镜像为tar,使用u盘等设备复制到任意docker主机,再次加载镜像
- 保存:docker save spring-boot-docker -o /home/spring-boot-docker.tar
- 加载:docker load -i spring-boot-docker.tar

6、阿里云操作

- 登录阿里云,密码就是开通镜像仓库时 的密码
  - docker login --username=icoding registry.cn-hangzhou.aliyuncs.com
- 拉取镜像
  - docker pull registry.cn-hangzhou.aliyuncs.com/icoding/i-nginx:v1.0
- 推送镜像
  - docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/icoding/icoding-nginx:v2
  - docker push registry.cn-hangzhou.aliyuncs.com/icoding/icoding-nginx:v2

Dockerfile详解
Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。

一般而言,Dockerfile可以分为四部分

基础镜像信息 维护者信息 镜像操作指令 启动时执行指令

指令说明
FROM指定基础镜像
MAINTAINER指定维护者信息,已经过时,可以使用LABEL maintainer=xxx 来替代
RUN运行命令 v
CMD指定启动容器时默认的命令 v
LABEL指定生成镜像的元数据标签信息 v
EXPOSE声明镜像内服务监听的端口 v
ENV指定环境变量,可以在docker run的时候使用-e改变 v
ADD复制指定的src路径下的内容到容器中的dest路径下,src可以为url会自动下载,可以为tar文件,会自动解压
COPY复制本地主机的src路径下的内容到镜像中的dest路径下,但不会自动解压等
ENTRYPOINT指定镜像的默认入口.运行命令 v
VOLUME创建数据卷挂载点
USER指定运行容器时的用户名或UID
WORKDIR配置工作目录,为后续的RUN、CMD、ENTRYPOINT指令配置工作目录
ARG指定镜像内使用的参数(如版本号信息等),可以在build的时候,使用–build-args改变 v
OBBUILD配置当创建的镜像作为其他镜像的基础镜像是,所指定的创建操作指令
STOPSIGNAL容器退出的信号值
HEALTHCHECK健康检查
SHELL指定使用shell时的默认shell类型

1、RUN、CMD、ENTRYPOINT区别

  1. RUN 执行命令并创建新的镜像层RUN 经常用于安装软件包(在构建镜像时运行的)。
  2. CMD 设置容器启动后默认执行的命令及其参数但 CMD 能够被 docker run 后面跟的命令行参数替换。
  3. ENTRYPOINT 配置容器启动时运行的命令。
  4. 以上命令都可以使用shell或者exec方式执行
  5. CMD ["executable","param1","param2"] (exec form, this is the preferred form)
  6. CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
  7. CMD command param1 param2 (shell form)

2、shell和exec方式

  1. shell 是 /bin/sh -c 的方式,

    1. exec ["/bin/sh","-c",command] 的方式== shell方式
      eg:shell方式
ENV name icoding  
ENTRYPOINT echo "Hello, $name" 
#输出 Hello icoding

ENTRYPOINT ["/bin/echo", "Hello, $name"]
#输出 Hello $name

ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
#输出 Hello icoding

##建议:CMD 和 ENTRYPOINT 推荐使用 Exec 格式因为指令可读性更强更容易理解。RUN 则两种格式都可以。exec的时候要获取环境变量等值,就用/bin/sh -c 即可。
No ENTRYPOINTENTRYPOINT exec_entry p1_entryENTRYPOINT [“exec_entry”, “p1_entry”]
No CMDerror, not allowed/bin/sh -c exec_entry p1_entryexec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”]p1_cmd p2_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd/bin/sh -c exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

实战Dockerfile

#1、ping命令小工具。
编写Dockerfile-->打包镜像--->根据这个镜像启动容器使用容器的功能
docker build -t hello .
-t:tag标签。镜像名字
.:在当前目录下工作
默认.这个目录下就得有一个 Dockerfile
FROM alpine
CMD ping baidu.com

#2、文件名不是Dockerfile。用-f 指定
docker build -f Dockerfile2 -t hello:v1.0 .
docker run -d --name hello hello;

#3、默认构建出来的镜像,放到了我们的本地镜像仓库。
	1)、登陆到dockerhub
	2)、dockehub国外,就算能Push,非常慢。阿里云加速的是下载。
	
#4、把这个镜像发布到Docker hub
	1)、docker login -u icodingallen;登陆到docker hub
	2)、docker push nginx:v1.0;推送过去。
	太慢了
#5、搭建私有的镜像仓库。使用阿里云的镜像仓库(免费)。
	1)、docker login --username=lyt_goodtogread@163.com registry.cn-hangzhou.aliyuncs.com

为了团队自治。只能看到自己的仓库的所有镜像。namespace;
创建镜像仓库。保存镜像各种版本,book: 1 2 3 4 5
docker tag hello:v1.0 registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.3
docker push registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.3

在这里插入图片描述
在这里插入图片描述
docker.io/libarary/hello:latest
registry.cn-hangzhou.aliyuncs.com/icodingdocker/hello:v1.0

镜像—》打包–》上传。

Dockerfile区分一些易混淆的指令

1、USER 执行cmd等之类命令的使用那个用户

alpine  sudo   gosu
FROM centos
RUN groupadd -r abc && useradd -r -g abc aaa
USER aaa
CMD whoami
# CMD 就是容器启动以后要执行的命令

2、ARG、ENV

  • The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build :arg在构建期间。docker build
  • The environment variables set using ENV will persist when a container is run from the resulting image. You can view the values using docker inspect, and change them using docker run --env =. env在运行是可以用到的
FROM alpine

ARG bbb haha
ENV abc 666

CMD echo $bbb
容器运行的时候arg的东西拿不到

CMD echo $abc
容器运行的时候env的能拿到


FROM alpine

ARG bbb haha
ENV abc=$bbb

CMD echo $abc

ARG指定的值,在镜像构建的后面位置,构建期间都可以使用到。

改变这些值行不行
docker build -f Dockerfile-arg-env -t file-arg --build-arg bbb=888 --build-arg abc=777 .
结果888 


# 构建时 bbb=888 abc=777 ,cmd打印888.原因 构建时不能改变env
# 运行时 
\ARGENV
build时√。–build-arg改变 构建参数(ARG声明)生效,能不能改(不能)
运行时不生效生效。能改 -e abc

最佳实战:

ARG:定义一些版本信息

​		FROM alpine 

​    ARG version=1

​	 RUN yum install nginx:$version

Env:运行时的环境变量。

ENV  env = --spring.profile.active=prod

​	-e修改。sb java -jar xxx.jar $env 

3、ADD和COPY

#构建了一个SpringBoot镜像。 xxx.jar 
/opt

docker build -t hello .

ADD:将当前目录下的内容放到镜像里面一起打包。

COPY:将当前目录下的内容放到镜像里面一起打包。

ADD ["","",""] dest:容器里面的目录
可以指定很多种路径地址。自动下载,解压复制。

FROM alpine

ADD hello.tar /opt/hello

COPY hello.tar /opt/world/

CMD echo "1234"

这个东西构建的镜像为什么docker run -d 不行。因为容器运行的是ech 1234;
没有一个守护进程一直运行。
CMD ping baidu.com

4、VOLUME和WORKDIR

VOLUME:指定容器需要挂载的卷
WORKDIR:工作目录。
	1、以后的其他命令在这个目录里面运行
	2、exec进去都默认来到了 WORKDIR 指定的目录。sh
	docker run -it --rm file-volume sh
	
WORKDIR


WORKDIR /root  == RUN cd /root

挂载麻烦。自动挂载。
FROM alpine

WORKDIR /opt/a

VOLUME /opt/b

COPY hello.txt .

ADD hello.tar /opt/b

CMD whoami

volume声明的挂载目录,即使容器运行的时候,不用-v进行挂载。docker也会自动的进行匿名挂载。
nginx:

5、RUN、CMD、ENTRYPOINT

相同点:运行命令

不同点:

​	RUN:在构建镜像的时候运行的命令
**CMD、ENTRYPOINT:在容器启动运行的命令**

测试RUN;

#想构建一个具有git功能的镜像。

FROM centos

RUN yum install -y git

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
CMD echo "git clone success"
#CMD 容器运行的时候CMD的命令才执行。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
相同的镜像layer层发生变化,只有这层变化。

  • -RUN指令的所有命令都在镜像docker build期间就执行
  • CMD和ENTRYPOINT在容器启动时运行
    • CMD 容器运行的时候CMD的命令才执行。docker run -it --rm file-run bash 能进容器中
    • 替换为ENTRYPOINT。虽然指令运行了。但是 docker run -it --rm file-run bash 。最后的bash没有进去,失效了。

无论是CMD还是ENTRYPOINT还是RUN

- `RUN ` (*shell* form, the command is run in a shell, which by default is `/bin/sh -c` on Linux or `cmd /S /C` on Windows)  RUN yum install -y git;`/bin/sh -c`可以动态获取一些变量
- `RUN ["executable", "param1", "param2"]` (*exec* form);无法动态获取一些变量
FROM centos

ARG soft=git
RUN ["yum install","-y","$soft"] #这是错误的。因为非`/bin/sh -c`方式,用不到前面声明的ARG,ENV

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
ENTRYPOINT echo "git clone success"

在这里插入图片描述

# bash-c 和 数组方式的区别,  修改后的;安装正确。
FROM centos

ARG soft=git
RUN ["/bin/sh","-c","yum install -y $soft"]
#-c command:后免是完整命令
WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data
ENTRYPOINT echo "git clone success"

RUN、CMD、ENTRYPOINT都支持一下两种方式

The exec form, which is the preferred form:
ENTRYPOINT [“executable”, “param1”, “param2”]

The shell form:

ENTRYPOINT command param1 param2

总结:

  • 如果运行命令是。[]方式,默认不是bash -c就无法用变化,普通的方式RUN yum -install -y $soft可以使用变量。

  • CMD、ENTRYPOINT的最佳实战

    • Dockerfile文件必须至少有一个 CMD 或者ENTRYPOINT 命令.
    • ENTRYPOINT 用来定义容器如何运行.
    • CMD 应该被用来作为给ENTRYPOINT 传递。默认参数的一种方式
    • CMD 将会被覆盖,容器运行时指定参数的时候. ENTRYPOINT 命令不会被覆盖。
    • CMD多个只会有一个生效。
    • ENTRYPOINT :不被传入的指令覆盖,但是多个也只有一个生效。

    为什么我的指令Dockerfile写CMD的时候,docker run -it --rm file-run bash可以进控制台,而ENTRYPOINT 不行?

    运行效果:

    • Dockerfile是CMD;没打印git clone success。但是bash生效。
      在这里插入图片描述

Dockerfile 是 ENTRYPOINT;打印了git clone success但是没有进容器(bash没生效)
在这里插入图片描述
混写。CMD + ENTRYPOINT

FROM centos

ARG soft=git
RUN ["/bin/bash","-c","yum install -y $soft"]

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data


CMD ["nginx"] #CMD给entrypoint提供参数
ENTRYPOINT ["yum","install","-y"]


```powershell
运行:
docker run -it --rm file-run maven

FROM centos

ARG soft=git
RUN ["/bin/bash","-c",“yum install -y $soft”]

WORKDIR /opt/data

RUN git clone https://gitee.com/lanoox/luject.git

VOLUME /opt/data

CMD ["","","",""] #可以放空
ENTRYPOINT ["/bin/sh","-c",“yum install -y”]

#容器启动就是yum install -y “”;自己启动命令加上git
CMD 后面有N参数。传了参数替换N个还是最后一个?
docker run -it --rm file-run maven CMD [“maven”] 对
docker run -it --rm file-run maven CMD [“”,“”,“maven”] 错

目的:构建镜像。SpringBoot编写的微服务,怎么做镜像?

1、运行的业务的目标环境?SB服务。java环境。FROM

2、怎么启动业务的。得到jar包,java -jar xxx.jar --spring.profile.active=prod --server.port=8080;决定镜像的ENTRYPOINT怎么写。docker exec?docker run(第一次容器启动要执行)?

docker exec haha -it bash【和entrypoint,cmd没啥关系】;

3、业务运行的时候需要啥?java。jar。jar包就想办法放进镜像中。COPY 。ADD

4、业务的那些数据是需要做持久化。VOLUME怎么写。

```powershell
FROM java:8


#服务器只有dockerfile和jar在一起
COPY *.jar /app.jar

#即使运行没有-v,也会匿名挂载
VOLUME ["/logs"]

CMD ["--server.port=8080"]

EXPOSE ["8080"]

ENTRYPOINT ["java","-jar","/app.jar"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值