Docker就该这么学--第一个dockerfile镜像文件
第一个dockerfile文件
利用docker快速安装一个redis镜像,了解dockerFile指令
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
具体的我们查看给大家的pdf的书籍,命令都是简单的,我们会慢慢的去学习这种方式是比较流行的方式。
就是将需要对镜像的操作全部写到一个文件中,然后使用docker build命令从这个文件中创建镜像。
这种方法可以使镜像的创建变得透明化和独立化,并且创建过程可以被重复执行。
dockerfile文件以行位单位,首为dockerfile命令,命令都是大写形式,期后紧跟着的是命令的参数。
dockerfile指令
FROM 指定基础镜像
指定待扩展的父级镜像。
除了注释外,在文件开头必须是一一个FROM指令, 接下来白指令便在这个父级镜像的环境中运行,直到遇到下一一个FROM指令。
通过添加多个FROM命令可以在同一个Dockerfile文件中创建多个镜像。
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。
就像我们之前运行了一个redis镜像的容器,再进行修改一样,基础镜像是必须指定的。
而 FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
在 Docker Store 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如nginx 、 redis 、 mongo 、 mysql 、 httpd 、 php 、 tomcat 等;
如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如ubuntu 、 debian 、 centos、 alpine 等这些操作系统的软件库
一般会以alpine为主,因为节约的资源比较少
RUN 执行命令
RUN 指令是用来执行命令行命令的。
格式:
RUN \<command\> (类似/bin/sh -cshell格式)
RUN ["executable", "param1", "param2"] (exec格式)
类似shell脚本风格的:
FROM alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add gcc g++ libc-dev wget vim openssl-dev make linux-headers
RUN mkdir -p /usr/src/redis
RUN cd /usr/src/redis
RUN wget -O redis-4.0.11.tar.gz "http://download.redis.io/releases/redis-4.0.11.tar.gz"
RUN tar -xzf redis-4.0.11.tar.gz -C /usr/src/redis
RUN cd /usr/src/redis/redis-4.0.11 && make && make PREFIX=/usr/local/redis install
MAINTAINER
用来声明创建的镜像的作者信息。在上述代码中,xxh是用户名,xxh@qq.co .是邮箱。这个命令并不是必需的。
EXPOSE
用来指明容器内进程对外开放的端口,多个端口之间使用空替隔力。
运行容器通过参数-p(大写)即可将EXPOSE里所指定的端口映射到主机上另外的随机端口,容器或主机就可以通过映射后的端口与此容器通信。
同时,我们也可以通过-p (小写)参数将dockerfile中EXPOSE中没有列出的端口设置成公开的。
ADD
向新镜像中添加文件,这个文件可以是一个主机文件,也可以是一个网络文件, 也可以是一个文件夹
ENV
设置容器运行的环境变量。在运行容器的时候,通过-e参数可以修改这个环境变量值,也可以添加新的环境变量:
Dockerfile使用注意事项
Dockerfile 中每一个指令都会建立一层, RUN 也不例外。
每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后, commit这一层的修改,构成新的镜像。
使用 Dockerfile 定制镜像而上面的这种写法,创建了很多层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。
结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。
这是很多初学Docker 的人常犯的一个错误。
Union FS是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。
dockerfile构建redis镜像
创建一个Dockerfile的文件,注意没有后缀(文件名也可以不叫Dockerfile,但是docker默认找的就是这个文件,如果不是则需要指定)
我们通过如下命令构建redis6的镜像
FROM centos
RUN groupadd -r redis && useradd -r -g redis redis
RUN yum update -y && yum install epel-release -y
RUN yum install wget -y && yum -y install bzip2
RUN wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-7.1.0/gcc-7.1.0.tar.gz
RUN mkdir -p /usr/src/gcc
RUN tar -xvf gcc-7.1.0.tar.gz -C /usr/src/gcc
RUN cd /usr/src/gcc/gcc-7.1.0 && ./contrib/download_prerequisites
RUN mkdir /usr/src/gcc/gcc-7.1.0/build
RUN cd /usr/src/gcc/gcc-7.1.0/build && ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
RUN cd /usr/src/gcc/gcc-7.1.0/build && make && make install
RUN wget https://github.com/antirez/redis/archive/6.0-rc2.tar.gz
RUN mkdir -p /usr/src/redis
RUN tar -zxvf 6.0-rc2.tar.gz -C /usr/src/redis
RUN cd /usr/src/redis/redis-6.0-rc2/ && CC=/usr/local/bin/gcc make && make install
执行命令
docker build -t redis6-test .
只是因为一些软件的关系构建比较慢这儿需要跳过改为构建redis5的镜像
FROM centos
RUN groupadd -r redis && useradd -r -g redis redis
RUN yum update -y && yum install epel-release -y
RUN yum install wget -y && yum -y install gcc automake autoconf libtool make
RUN yum install gcc gcc-c++ -y
RUN mkdir -p /usr/src/redis
RUN wget https://github.com/antirez/redis/archive/5.0.7.tar.gz
RUN tar -zxvf 5.0.7.tar.gz -C /usr/src/redis
RUN cd /usr/src/redis/redis-5.0.7 && make && make PREFIX=/usr/local/redis install
docker build -t redis5 .
根据上面的运行结果我们可以看到在执行一行RUN之后就会出现一个 ---> Running in xxxx 的信息,对于dockerfile的知心来说它会没执行一行命令就会创建一个临时镜像,然后下面的命令就会基于这个镜像继续构建,构建完就删除前面的镜像,直到最后一步生成我们的目标镜像。
在dockerfile使用注意事项
在docker中的设计是采用文件系统,而在dockerfile中一个RUN代表一层曾经是最大不得超过 42 层,现在是不得超过 127 层。
而且在docker中下载的文件是会占用一定的资源,对于容器我们是尽量占用足够小的资源所以下载安装之后就要删除文件。对于命令之间我们通常是建议一些能一起执行的命令放在一起执行可通过“"分割
所以对于上面的错误主要包含有
1. 下载安装的文件没有删除
2. RUN的层次太多
所以正确的写法应该如下
FROM centos
RUN groupadd -r redis && useradd -r -g redis redis
RUN yum update -y ; \
yum -y install gcc automake autoconf libtool make wget epel-release gcc-c++;
RUN mkdir -p /usr/src/redis; \
wget https://github.com/antirez/redis/archive/5.0.7.tar.gz; \
tar -zxvf 5.0.7.tar.gz -C /usr/src/redis; \
rm -rf 5.0.7.tar.gz; \
cd /usr/src/redis/redis-5.0.7 && make && make PREFIX=/usr/local/redis install;
别忘了通过docker images查看
docker hub发布
这个有点类似于composer的仓库地址就是用来存储我们开会人员的镜像地址的;
官网:https://hub.docker.com
自己注册一个账号,这个过程我就跳过
~ docker login
Username: dreamfishliu
Password: ************
Login Successded
docker hub异常
在上面执行的代码可能出现如下异常 rror response from daemon: Get https://registry-1.docker.io/v2/library/hello-world/manifest
这个问题的异常主要是
- 解析ip不可用
- 是因为dns域名没有解析的原因;
~ yum install bind-utils
~ dig @114.114.114.114 registry-1.docker.io
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @114.114.114.114 registry-1.docker.io
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57840
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;registry-1.docker.io. IN A
;; ANSWER SECTION:
registry-1.docker.io. 33 IN A 34.205.88.205
registry-1.docker.io. 33 IN A 35.169.133.189
registry-1.docker.io. 33 IN A 34.202.247.184
registry-1.docker.io. 33 IN A 3.224.11.4
registry-1.docker.io. 33 IN A 3.82.34.201
registry-1.docker.io. 33 IN A 34.195.36.112
registry-1.docker.io. 33 IN A 3.221.133.86
registry-1.docker.io. 33 IN A 3.224.75.242
;; Query time: 26 msec
;; SERVER: 114.114.114.114#53(114.114.114.114)
;; WHEN: 三 4月 22 04:41:31 CST 2020
;; MSG SIZE rcvd: 177
~ vi /etc/hosts
34.205.88.205 registry-1.docker.io
~ systemctl restart docker
登入成功之后,使用push命令就可以上传镜像,如果不指定tag则本地的镜像都会上传。如下实例:
注意docker hub的push要求是如下格式
docker push 注册名/镜像名:tag
因为我们创建的镜像是redis5不符合规划
[root@localhost 01]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis5 latest 49071214d162 34 minutes ago 774MB
centos latest 470671670cac 3 months ago 237MB
执行tag修改
[root@localhost 01]# docker tag redis5 shineyork/redis5:v1
[root@localhost 01]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis5 latest 49071214d162 44 minutes ago 774MB
shineyork/redis5 v1 49071214d162 44 minutes ago 774MB
centos latest 470671670cac 3 months ago 237MB
建议可以先在dockerhub中建议仓库
[root@localhost 01]# docker push shineyork/redis5:v1
The push refers to repository [docker.io/shineyork/redis5]
20c820832bb0: Layer already exists
9b476962a36c: Layer already exists
89594a1f898a: Layer already exists
0683de282177: Layer already exists
v1: digest: sha256:056d54c22dd8af8f765baf9fc78ac4a0772c4ee7fddabccaeae80845ed7edb7b size: 1162
然后我们可以rmi掉本地的镜像,pull我们自己上传的镜像
[root@localhost 01]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 470671670cac 3 months ago 237MB
[root@localhost 01]# docker pull shineyork/redis5:v1
v1: Pulling from shineyork/redis5
8a29a15cefae: Pull complete
46bec8964c2b: Pull complete
db4fd5d9e637: Pull complete
395f6c8aea1b: Pull complete
Digest: sha256:056d54c22dd8af8f765baf9fc78ac4a0772c4ee7fddabccaeae80845ed7edb7b
Status: Downloaded newer image for shineyork/redis5:v1
[root@localhost 01]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
shineyork/redis5 v1 49071214d162 13 hours ago 774MB
centos latest 470671670cac 3 months ago 237MB