docker

 

centos7如何使用国内镜像快速安装最新版本docker-ce

1.yum快速安装docker

在/etc/yum.repos.d/下新建文件docker-ce.repo 文件,这里创建国内的一个yum源

然后执行命令

yum  clean all

rm -rf /var/cache/yum

yum makecache
sudo yum install docker-ce -y

 

vim /etc/yum.repos.d/docker-ce.repo
[docker-ce-stable] name=Docker CE Stable - $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/stable enabled=1 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-stable-debuginfo] name=Docker CE Stable - Debuginfo $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/stable enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-stable-source] name=Docker CE Stable - Sources baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/stable enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-edge] name=Docker CE Edge - $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-edge-debuginfo] name=Docker CE Edge - Debuginfo $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-edge-source] name=Docker CE Edge - Sources baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/edge enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-test] name=Docker CE Test - $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-test-debuginfo] name=Docker CE Test - Debuginfo $basearch baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/debug-$basearch/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg [docker-ce-test-source] name=Docker CE Test - Sources baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/source/test enabled=0 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg

 

2.docker启动
systemctl start docker.service
3.如需使用docker提供的api远程访问功能运行:

dockerd -H unix:///var/run/docker.sock -H tcp://你的主机地址和端口,默认2375端口 &

 

 

 

docker 常用命令

查找镜像
https://hub.docker.com/
search  --> centos7
 
一般docker 会有一个基础镜像,中间件镜像,应用镜像,生成一个镜像
 
docker build  通过dockerfile生成镜像
docker images  查看当前本地有哪些docker镜像
docker run 通过docker镜像生成docker容器(docker help run 查看run命令)
docker ps  查看正在up运行中的docker镜像,docker ps -a 查看所有的
docker exec 进入容器
docker rm   删除容器,-f 强制删除,up状态的也可以删除
docker stop  停止提一个容器
docker start  启动一个容器
docker tag   给镜像打标签(docker tag imageid name:tag)
docker rmi <image id>  删除images,通过image的id来指定删除谁

 

 
 
 
 
git clone https://git.oschina.net/99fu/security.git
 
docker 镜像地址  docker pull centos
 
 
dockerfile 是自动构建docker镜像的配制文件。
 
进入到git下,进入centos7目录下
docker build是用dockerfile生成docker镜像,每个add,生成一个docker layer
# docker build -t  fu/centos:7.0 .
-t 给镜像取名字
 
完整命令规则: 
docker build -t registry_url/namespace/imageName:version ./path  
(--如果没写vestion默契为latest最新的   .如果dockerfile在当前目录下,只用.就可以,否则加上dockerfile路径)
 
#docker run -it -d -p 2222:22 --name base fu/centos:7.0
-it 交互模式,前台启动
-d   后端其动,返回id号
-p   小p,如果用 9999:22,重启后还是用指定端口映射,如果占用,报错 
-P    大P,自动找无人使用的端口映射,如果服务器重启,就会随机用个别的端口映射
--name 给容器取个名字

 

fu/centos:7.0 用哪个镜像启动容器,如果容器在本地不存在,则远程pull,找不到则报错
(
Unable to find image 'csphere/centos7:7.1' locally
Pulling repository docker.io/csphere/centos7
docker: Error: image csphere/centos7:7.1 not found.
See 'docker run --help'.
)

 

 
 
docker exec -it website /bin/bash
exec 进入容器
-it 交互模式
容器名称
/bin/bash 
(
docker help 中可以看出attach 也可以进入容器中,但是试过会有卡死现象
exit退出,container 还是处于up状态
容器是基于基础镜像生成的容器,所以具有centos的命令
)
 
构建中间件镜像myslq
进入mysql 
docker build -t fu/mysql:5.4 .
生成镜像
docker images 查看当前本地镜像
启动 mysql的docker容器
docker run -d -p 3306:3306 --name dbserver fu/mysql:5.4
返回id串,成功
docker ps 
查看是否启动container成功
docker exec -it dbserver /bin/bash
进入container
mysql
进入db里,可用mysql指令操作啦
 show databases;
 
刚才启动,没有给环境变量,就是用户与密码,用的默认的

 

 
删除容器,再试一次。
 
docker rm 只能删除非up状态的
docker rm 

 

 
启动容器 docker run -d -p 3306:3306 -v host_dir:container_dir  imageName  (host_dir:container_dir 用于宿主机与容器挂载,数据同步)
docker run -d -p 3306:3306 -v /var/lib/docker/vfs/dir/mydata:/var/lib/mysql cephere/mysql:5.4   (未设置--name 则自动生成一个name)

 

 
通过docke exec -it  [docke 容器名称或id全或id前几位可区分即可] /bin/bash
 
这次创建mysql用户,然后删除容器,再次创建容器,指定到挂载目录,看数是否能将历史自动载入进来。
create database mydb;
show databases;
exit;
exit
查看一下,docker是否创健了指定的挂在目录。
ls /var/lib/docker/vfs/dir/mydata/
停掉容器 docker stop id
删除mysql容器,docker rm  id
再次查看,看挂载目录是否存在
ls /var/lib/docker/vfs/dir/mydata/
 
再次创建一个容器,指定到挂载的目录,确认数据是否能够回来
docker run -d -p 3306:3306 --name newdb -v /var/lib/docker/vfs/dir/mydata:/var/lib/mysql fu/mysql:5.4
 docker ps
 docker exec -it newdb /bin/bash
 mysql
 show databases;
 可以看到数据库还存在
 
 创建应用
 应用里加入一个Dockerfile 和 init.sh
 .dockerignore文件,可以过滤掉,不须要copy的文件
 
 
 show databases;
 
 启动应用容器
 docker run -d -p 80:80 --name wordpress -e WORDPRESS_DB_HOST=192.168.80.241 -e WORDPRESS_DB_USER=admin -e WORDPRESS_DB_PASSWORD=cephere2015 cephere/wordpress:4.2
 
 
 
 
 docker-compose up
 【
如果docker-compose --version 为无效指令,则须安装docker-compose  组合
#下载安装
curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
#授权
chmod +x /usr/local/bin/docker-compose
#查版本号
docker-compose --version
#当前目录构建组合镜像。须存在docker-compose.yml文件
docker-compose up -d
 】
 

 

docker file

 

更准确的理解,或英文水平好的,建议直接看官方文档https://docs.docker.com/engine/reference/builder/,因为每个人的英语水平不同,理解能力不同。这节应该是比较难的一节,也是比较重要 一节。

Dockerfile是个文本文件,这个文件就以“Dockerfile”命名(至少默认就叫这个名子,而且就在软件的要目录下,可以在docker built时通过-f参数来指定这个Dockerfile的位置和名子),Docker能通过读取这个文件里的指令集来自动创建一个镜像。然后使用docker build命令,我们能创建出一个能执行一系列指令的镜像。

格式:

# Comment使用“#”注释
INSTRUCTION arguments
指令      参数

  指令是不分大小写的。(这个是我看了官方文档才知道,因为网上各大神都是指令大写的。)入乡随俗,国际惯例,指令大写,那就指令大写吧。

所有指令顶格编写

 

 

错误示范

无效的,因为使用了换行符

# direc \
tive=value

无效的,因为使用了两次

# directive=value1
# directive=value2

FROM ImageName

被当作注释,因为在一个构建指令之后。

FROM ImageName
# directive=value

被当作注释,因为前面还有注释。

# About my dockerfile
# directive=value
FROM ImageName

一个是未被识别的指令,会被当成注释,而下面那个却因为上面那个成了注释,尽管这是一个能被识别的指令,但也是被当作注释。

# unknowndirective=value
# knowndirective=value

以下的效果是一样的,空格不影响

1
2
3
4
5
#directive=value
# directive =value
#   directive= value
# directive = value
#     dIrEcTiVe=value

 escape转义,如果没有特殊指定,如下操作。那么系统默认“\”为作转义字符。

# escape=\   or # escape=`

 

ENV 

Environment replacement 环境置换

环境参数使用ENV来声明

1
ENV 设计环境变量。它们使用键值对,增加运行程序的灵活性。
ENV <key> <value> ENV <key>=<value> ...

 环境变理,可以使用$variable_name 或 ${variable_name}来表示。这些变量与shell有点类似。

如:

${variable:-word} 表示如果变量有东西就直接显示,如果为空,就使用word来代替
${variable:+word} 表示如果变量为word就显示word,否则,就为空。

要注意以下情况

ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc

def的结果是hello而不是bye,ghi的结果是bye。因为是不同部分的指令。

其它例子

ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

 

.dockerignore文件。一个被命名为.dockerignore的隐藏文件,如果他存在,Docker就会去找这个文件里的内容,出现在这个文件里的路径都会被忽略。

以下是一些.dockerignore的例子。

# comment
*/temp*
*/*/temp*
temp?

可使用通配符。

 

解析指令

在这个Dockerfile里的指令有:ADD,COPY,ENV,EXPOSE,FROM,LABEL,STOPSIGNAL,USER,VOLUME,WORKDIR

 

FROM

所有的Dockfile都必须以FROM命令开始。这个命令是指基于哪个镜像开始创建。下面是常见命令总表

FROM <image> [AS <name>]
or
FROM <image>[:<tag>] [AS <name>]
or
FROM <image>[@<digest>] [AS <name>]

ARG构建参数

ARG <arg name> [=<defaults value>]

ARG必须在FROM之前来声明参数,在后面的构建中是不会用到这个变量的。然后只有定义过的ARG才能在docker built 中使用--build-arg<参数名>=<值>
来覆盖。

 在一个Dockerfile里面,可出现多次FROM指令。

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

 

RUN/CMD/ENTRYPOINT

RUN

RUN <command>在shell或者exec的环境下要执行的命令。
RUN <command> (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 ["executable", "param1", "param2"] (exec form)

使用一次RUN就等于创建一层。所以链接使用RUN是没有必要的,要使用换行加&&的形式来表示

例如:

复制代码
FROM debian:jessie

RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install

可替换成
FROM debian:jessie

RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps
复制代码

这个我是参考https://github.com/yeasy/docker_practice/blob/master/image/build.md

首先,之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。

并且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。

此外,还可以看到这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。

很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。

 

复制代码
CMD 容器启动命令的三种形式,但CMD只能使用一次,多个CMD会抵消之前的指令。
CMD ["executable","param1","param2"](推荐这种json格式,要使用双引号,不使用单引号。)
CMD ["param1","param2"]作为一个参数向ENTRYPOINT传递
CMD command param1 param2

ENTRYPOIONT 配置容器一个可执行的命令与CMD比较相似,也是只能使用一次,多个命令会抵消之前的。它有两种形式
ENTRYPOIONT ["executable","param1","param2"]
ENTRYPOIONT command param1 param2
复制代码

CMD

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的

如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。推荐这种json格式,要使用双引号,不使用单引号。还有需要了解清命令启动容器,容器里的东西就生效,要是命令结束了,容器就生命周期就结束。所以要启动一个类似于service nginx start的命令时,实际是在运行init.d下的一个nginx的脚本。而执行这个脚本是sh 。当这个脚本被执行完后,程序就结束,容器就会被销毁。所以应该直接运行nginx命令。

ENTRYPOINT

这节参考来源于https://github.com/yeasy/docker_practice/blob/master/image/dockerfile/entrypoint.md

ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)

ENTRYPOINT 命令格式和RUN一样,而其目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。当我们定义了ENTRYPOINT后,CMD的含意就发生了改变,变成把CMD的内容作为参数传给ENTRYPOINT

<ENTRYPOINT> "<CMD>"

例子1:让镜像变成像命令一样使用

假设我们需要一个得知自己当前公网 IP 的镜像,那么可以先用 CMD 来实现:

FROM ubuntu:16.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://ip.cn" ]

假如我们使用 docker build -t myip . 来构建镜像的话,如果我们需要查询当前公网 IP,只需要执行:

$ docker run myip
如果再试
$ docker run myip -i 报错

改成

FROM ubuntu:16.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

则正常。其实每个一外来的参数就是一个CMD。之前使用CMD电把参数替换了CMD的位置,而ENTRYPOINT则是把CMD当成参数来替换他的参数部分。

场景二:应用运行前的准备工作

启动容器就是启动主进程,但有些时候,启动主进程前,需要一些准备工作。

比如 mysql 类的数据库,可能需要一些数据库配置、初始化的工作,这些工作要在最终的 mysql 服务器运行之前解决。

此外,可能希望避免使用 root 用户去启动服务,从而提高安全性,而在启动服务前还需要以 root 身份执行一些必要的准备工作,最后切换到服务用户身份启动服务。或者除了服务外,其它命令依旧可以使用 root 身份执行,方便调试等。

这些准备工作是和容器 CMD 无关的,无论 CMD 为什么,都需要事先进行一个预处理的工作。这种情况下,可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 <CMD>)作为命令,在脚本最后执行。比如官方镜像 redis 中就是这么做的:

复制代码
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD [ "redis-server" ]
复制代码

EXPOSE 6379 CMD [ "redis-server" ] 可以看到其中为了 redis 服务创建了 redis 用户,并在最后指定了 ENTRYPOINT 为 docker-entrypoint.sh 脚本。

复制代码
#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
    chown -R redis .
    exec su-exec redis "$0" "$@"
fi

exec "$@"
复制代码

该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行。比如:

$ docker run -it redis id uid=0(root) gid=0(root) groups=0(root)

 

 MAINTAINER <author name>镜像作者,从官方文档来看,这个参数是过时的,不建议使用的。官方提出使用标签来代替这个指令

MAINTAINER <name>
使用标签来代替这个指令
LABEL maintainer="SvenDowideit@home.org.au"


EXPOSE

暴露端口,指定容器在运行时监听的端口。不知道为什么在容器里喜欢说暴露。

EXPOSE <port> [<port>...]


ADD/COPY

复制代码
ADD <src>... <dest>
ADD ["<src>",... "<dest>"](推荐这种,即使有空格也好使)

ADD hom* /mydir/        # 复制所有以hom开头的文件
ADD hom?.txt /mydir/    # ? 能代替任意一个字符e.g., "home.txt"
ADD test relativeDir/          # 把"test" 复制到`WORKDIR`/relativeDir/
ADD test /absoluteDir/         # 把"test" 复制到绝对路径/absoluteDir/

有特殊字符即需要转义。
ADD arr[[]0].txt /mydir/ # copy a file named "arr[0].txt" to /mydir/

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
COPY hom* /mydir/
COPY hom?.txt /mydir/
复制代码

目标路径可以是容器内的绝对路径,也可以是相对于工作目录的相对路径。工作目录可使用WORKDIR来设定。
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
与ADD不同的是,ADD支持 URL。这个时候Docker会试图下载这个链接的文件放到目标路径。被下载的文件权限为600。如果需要调整权限需要使用RUN命令来调整。
如果<源路径>为一个tar压缩文件,压缩格式为gzip/bzip2/xz的话,ADD指令会自动解压文件到<目标路径>去
因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD

 

VOLUME定义匿名卷

这是比较重要一节,这是关系到数据持久化的问题。

复制代码
VOLUME ["/data"]
例:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
复制代码

这样的操作是自动挂载匿名卷,这样任何写在/data中的信息都不会记录在容器存储层。也可以在运行的时候代替这个data

在这里,我们可以定义,web目录、定义配置目录、定义数据库目录、定义日志目录等。

 

USER

USER <user>[:<group>] or
USER <UID>[:<GID>]

改变环境状态,影响到以后的层,使RUN/CMD/ENTRPOINT使用指定身份运行。

WORKDIR

WORKDIR 指定RUN/CMD/ENTRYPOINT命令的工作目录。
WORKDIR /PATH/TO/WORKDIR

用来设定RUN, CMD, ENTRYPOINT, COPY 和 ADD这些操作的默认路径。其参数如果是相对路径,则是相对于workdir的路径

 

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
=》/a/b/c

 

ONBUILD

ONBUILD [INSTRUCTION]

这个命令后面接其RUN/COPY等指令,但个在当前镜像构建时并不会执行,而是在下次构建时才会执行的。

 

HEALTHCHECK

HEALTHCHECK 设置检查容器的健康情况
HEALTHCHECK [option] <command>
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令


LABEL标签

LABEL <key>=<value> <key>=<value> <key>=<value> ...

标签指令能为镜像增加元数据,一个标签就是一个键值对。
可以使用引号或反斜杠。

举个粟子:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

一个镜像,可以有一个或多个标签,多个标签也可以写成一个命令行。例如:

LABEL multi.label1="value1" multi.label2="value2" other="value3"
等效于
LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

 

 

#!/bin/sh
set -e
#
# This script is meant for quick & easy install via:
#   'curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh'
# or:
#   'wget -qO- http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh'
#
# For test builds (ie. release candidates):
#   'curl -fsSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/test/internet | sh'
# or:
#   'wget -qO- http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/test/internet | sh'
#
# For experimental builds:
#   'curl -fsSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/experimental/internet | sh'
# or:
#   'wget -qO- http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/experimental/internet | sh'
#
# Docker Maintainers:
#   To update this script on https://get.docker.com,
#   use hack/release.sh during a normal release,
#   or the following one-liner for script hotfixes:
#     aws s3 cp --acl public-read hack/install.sh s3://get.docker.com/index
#

url="http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet"
apt_url="http://mirrors.aliyun.com/docker-engine/apt"
yum_url="http://mirrors.aliyun.com/docker-engine/yum"
gpg_fingerprint="58118E89F3A912897C070ADBF76221572C52609D"

key_servers="
ha.pool.sks-keyservers.net
pgp.mit.edu
keyserver.ubuntu.com
"

command_exists() {
    command -v "$@" > /dev/null 2>&1
}

echo_docker_as_nonroot() {
    if command_exists docker && [ -e /var/run/docker.sock ]; then
        (
            set -x
            $sh_c 'docker version'
        ) || true
    fi
    your_user=your-user
    [ "$user" != 'root' ] && your_user="$user"
    # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
    cat <<-EOF

    If you would like to use Docker as a non-root user, you should now consider
    adding your user to the "docker" group with something like:

      sudo usermod -aG docker $your_user

    Remember that you will have to log out and back in for this to take effect!

    EOF
}

# Check if this is a forked Linux distro
check_forked() {

    # Check for lsb_release command existence, it usually exists in forked distros
    if command_exists lsb_release; then
        # Check if the `-u` option is supported
        set +e
        lsb_release -a -u > /dev/null 2>&1
        lsb_release_exit_code=$?
        set -e

        # Check if the command has exited successfully, it means we're in a forked distro
        if [ "$lsb_release_exit_code" = "0" ]; then
            # Print info about current distro
            cat <<-EOF
            You're using '$lsb_dist' version '$dist_version'.
            EOF

            # Get the upstream release info
            lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[[:space:]]')
            dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[[:space:]]')

            # Print info about upstream distro
            cat <<-EOF
            Upstream release is '$lsb_dist' version '$dist_version'.
            EOF
        else
            if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ]; then
                # We're Debian and don't even know it!
                lsb_dist=debian
                dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')"
                case "$dist_version" in
                    8|'Kali Linux 2')
                        dist_version="jessie"
                    ;;
                    7)
                        dist_version="wheezy"
                    ;;
                esac
            fi
        fi
    fi
}

rpm_import_repository_key() {
    local key=$1; shift
    local tmpdir=$(mktemp -d)
    chmod 600 "$tmpdir"
    for key_server in $key_servers ; do
        gpg --homedir "$tmpdir" --keyserver "$key_server" --recv-keys "$key" && break
    done
    gpg --homedir "$tmpdir" -k "$key" >/dev/null
    gpg --homedir "$tmpdir" --export --armor "$key" > "$tmpdir"/repo.key
    rpm --import "$tmpdir"/repo.key
    rm -rf "$tmpdir"
}

semverParse() {
    major="${1%%.*}"
    minor="${1#$major.}"
    minor="${minor%%.*}"
    patch="${1#$major.$minor.}"
    patch="${patch%%[-.]*}"
}

do_install() {
    case "$(uname -m)" in
        *64)
            ;;
        *)
            cat >&2 <<-'EOF'
            Error: you are not using a 64bit platform.
            Docker currently only supports 64bit platforms.
            EOF
            exit 1
            ;;
    esac

    if command_exists docker; then
        version="$(docker -v | awk -F '[ ,]+' '{ print $3 }')"
        MAJOR_W=1
        MINOR_W=10

        semverParse $version

        shouldWarn=0
        if [ $major -lt $MAJOR_W ]; then
            shouldWarn=1
        fi

        if [ $major -le $MAJOR_W ] && [ $minor -lt $MINOR_W ]; then
            shouldWarn=1
        fi

        cat >&2 <<-'EOF'
            Warning: the "docker" command appears to already exist on this system.

            If you already have Docker installed, this script can cause trouble, which is
            why we're displaying this warning and provide the opportunity to cancel the
            installation.

            If you installed the current Docker package using this script and are using it
        EOF

        if [ $shouldWarn -eq 1 ]; then
            cat >&2 <<-'EOF'
            again to update Docker, we urge you to migrate your image store before upgrading
            to v1.10+.

            You can find instructions for this here:
            https://github.com/docker/docker/wiki/Engine-v1.10.0-content-addressability-migration
            EOF
        else
            cat >&2 <<-'EOF'
            again to update Docker, you can safely ignore this message.
            EOF
        fi

        cat >&2 <<-'EOF'

            You may press Ctrl+C now to abort this script.
        EOF
        ( set -x; sleep 20 )
    fi

    user="$(id -un 2>/dev/null || true)"

    sh_c='sh -c'
    if [ "$user" != 'root' ]; then
        if command_exists sudo; then
            sh_c='sudo -E sh -c'
        elif command_exists su; then
            sh_c='su -c'
        else
            cat >&2 <<-'EOF'
            Error: this installer needs the ability to run commands as root.
            We are unable to find either "sudo" or "su" available to make this happen.
            EOF
            exit 1
        fi
    fi

    curl=''
    if command_exists curl; then
        curl='curl -sSL'
    elif command_exists wget; then
        curl='wget -qO-'
    elif command_exists busybox && busybox --list-modules | grep -q wget; then
        curl='busybox wget -qO-'
    fi

    # check to see which repo they are trying to install from
    if [ -z "$repo" ]; then
        repo='main'
        if [ "http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/test/internet" = "$url" ]; then
            repo='testing'
        elif [ "http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/experimental/internet" = "$url" ]; then
            repo='experimental'
        fi
    fi

    # perform some very rudimentary platform detection
    lsb_dist=''
    dist_version=''
    if command_exists lsb_release; then
        lsb_dist="$(lsb_release -si)"
    fi
    if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then
        lsb_dist="$(. /etc/lsb-release && echo "$DISTRIB_ID")"
    fi
    if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then
        lsb_dist='debian'
    fi
    if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then
        lsb_dist='fedora'
    fi
    if [ -z "$lsb_dist" ] && [ -r /etc/oracle-release ]; then
        lsb_dist='oracleserver'
    fi
    if [ -z "$lsb_dist" ]; then
        if [ -r /etc/centos-release ] || [ -r /etc/redhat-release ]; then
            lsb_dist='centos'
        fi
    fi
    if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then
        lsb_dist="$(. /etc/os-release && echo "$ID")"
    fi

    lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"

    case "$lsb_dist" in

        ubuntu)
            if command_exists lsb_release; then
                dist_version="$(lsb_release --codename | cut -f2)"
            fi
            if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
                dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
            fi
        ;;

        debian)
            dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')"
            case "$dist_version" in
                8)
                    dist_version="jessie"
                ;;
                7)
                    dist_version="wheezy"
                ;;
            esac
        ;;

        oracleserver)
            # need to switch lsb_dist to match yum repo URL
            lsb_dist="oraclelinux"
            dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//' | sort -r | head -1)"
        ;;

        fedora|centos)
            dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//' | sort -r | head -1)"
        ;;

        *)
            if command_exists lsb_release; then
                dist_version="$(lsb_release --codename | cut -f2)"
            fi
            if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
                dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
            fi
        ;;


    esac

    # Check if this is a forked Linux distro
    check_forked

    # Run setup for each distro accordingly
    case "$lsb_dist" in
        amzn)
            (
            set -x
            $sh_c 'sleep 3; yum -y -q install docker'
            )
            echo_docker_as_nonroot
            exit 0
            ;;

        'opensuse project'|opensuse)
            echo 'Going to perform the following operations:'
            if [ "$repo" != 'main' ]; then
                echo '  * add repository obs://Virtualization:containers'
            fi
            echo '  * install Docker'
            $sh_c 'echo "Press CTRL-C to abort"; sleep 3'

            if [ "$repo" != 'main' ]; then
                # install experimental packages from OBS://Virtualization:containers
                (
                    set -x
                    zypper -n ar -f obs://Virtualization:containers Virtualization:containers
                    rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
                )
            fi
            (
                set -x
                zypper -n install docker
            )
            echo_docker_as_nonroot
            exit 0
            ;;
        'suse linux'|sle[sd])
            echo 'Going to perform the following operations:'
            if [ "$repo" != 'main' ]; then
                echo '  * add repository obs://Virtualization:containers'
                echo '  * install experimental Docker using packages NOT supported by SUSE'
            else
                echo '  * add the "Containers" module'
                echo '  * install Docker using packages supported by SUSE'
            fi
            $sh_c 'echo "Press CTRL-C to abort"; sleep 3'

            if [ "$repo" != 'main' ]; then
                # install experimental packages from OBS://Virtualization:containers
                echo >&2 'Warning: installing experimental packages from OBS, these packages are NOT supported by SUSE'
                (
                    set -x
                    zypper -n ar -f obs://Virtualization:containers/SLE_12 Virtualization:containers
                    rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
                )
            else
                # Add the containers module
                # Note well-1: the SLE machine must already be registered against SUSE Customer Center
                # Note well-2: the `-r ""` is required to workaround a known issue of SUSEConnect
                (
                    set -x
                    SUSEConnect -p sle-module-containers/12/x86_64 -r ""
                )
            fi
            (
                set -x
                zypper -n install docker
            )
            echo_docker_as_nonroot
            exit 0
            ;;

        ubuntu|debian)
            export DEBIAN_FRONTEND=noninteractive

            did_apt_get_update=
            apt_get_update() {
                if [ -z "$did_apt_get_update" ]; then
                    ( set -x; $sh_c 'sleep 3; apt-get update || true' )
                    did_apt_get_update=1
                fi
            }

            # aufs is preferred over devicemapper; try to ensure the driver is available.
            if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
                if uname -r | grep -q -- '-generic' && dpkg -l 'linux-image-*-generic' | grep -qE '^ii|^hi' 2>/dev/null; then
                    kern_extras="linux-image-extra-$(uname -r) linux-image-extra-virtual"

                    apt_get_update
                    ( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true

                    if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
                        echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)'
                        echo >&2 ' but we still have no AUFS.  Docker may not work. Proceeding anyways!'
                        ( set -x; sleep 10 )
                    fi
                else
                    echo >&2 'Warning: current kernel is not supported by the linux-image-extra-virtual'
                    echo >&2 ' package.  We have no AUFS support.  Consider installing the packages'
                    echo >&2 ' linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.'
                    ( set -x; sleep 10 )
                fi
            fi

            # install apparmor utils if they're missing and apparmor is enabled in the kernel
            # otherwise Docker will fail to start
            if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then
                if command -v apparmor_parser >/dev/null 2>&1; then
                    echo 'apparmor is enabled in the kernel and apparmor utils were already installed'
                else
                    echo 'apparmor is enabled in the kernel, but apparmor_parser missing'
                    apt_get_update
                    ( set -x; $sh_c 'sleep 3; apt-get install -y -q apparmor' )
                fi
            fi

            if [ ! -e /usr/lib/apt/methods/https ]; then
                apt_get_update
                ( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https ca-certificates' )
            fi
            if [ -z "$curl" ]; then
                apt_get_update
                ( set -x; $sh_c 'sleep 3; apt-get install -y -q curl ca-certificates' )
                curl='curl -sSL'
            fi
            (
            set -x
            for key_server in $key_servers ; do
                $sh_c "apt-key adv --keyserver hkp://${key_server}:80 --recv-keys ${gpg_fingerprint}" && break
            done
            $sh_c "apt-key adv -k ${gpg_fingerprint} >/dev/null"
            $sh_c "mkdir -p /etc/apt/sources.list.d"
            $sh_c "echo deb [arch=$(dpkg --print-architecture)] ${apt_url}/repo ${lsb_dist}-${dist_version} ${repo} > /etc/apt/sources.list.d/docker.list"
            $sh_c "sleep 3; apt-get update || true; if [ -z \"$docker_version\" ] ; then apt-get install -y -q docker-engine; else apt-get install -y -q docker-engine=${docker_version}-0~${dist_version}; fi"
            )
            echo_docker_as_nonroot
            exit 0
            ;;

        fedora|centos|oraclelinux)
            $sh_c "cat >/etc/yum.repos.d/docker-${repo}.repo" <<-EOF
            [docker-${repo}-repo]
            name=Docker ${repo} Repository
            baseurl=${yum_url}/repo/${repo}/${lsb_dist}/${dist_version}
            enabled=1
            gpgcheck=1
            gpgkey=${yum_url}/gpg
            EOF
            if [ "$lsb_dist" = "fedora" ] && [ "$dist_version" -ge "22" ]; then
                (
                    set -x
                    $sh_c 'sleep 3; dnf -y -q install docker-engine'
                )
            else
                (
                    set -x
                    $sh_c "sleep 3; yum -y -q update; if [ -z \"$docker_version\" ] ; then yum -y -q install docker-engine; else yum -y -q install docker-engine-$docker_version; fi"
                )
            fi
            echo_docker_as_nonroot
            exit 0
            ;;
        gentoo)
            if [ "$url" = "http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/test/internet" ]; then
                # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output
                cat >&2 <<-'EOF'

                  You appear to be trying to install the latest nightly build in Gentoo.'
                  The portage tree should contain the latest stable release of Docker, but'
                  if you want something more recent, you can always use the live ebuild'
                  provided in the "docker" overlay available via layman.  For more'
                  instructions, please see the following URL:'

                    https://github.com/tianon/docker-overlay#using-this-overlay'

                  After adding the "docker" overlay, you should be able to:'

                    emerge -av =app-emulation/docker-9999'

                EOF
                exit 1
            fi

            (
                set -x
                $sh_c 'sleep 3; emerge app-emulation/docker'
            )
            exit 0
            ;;
    esac

    # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output
    cat >&2 <<-'EOF'

      Either your platform is not easily detectable, is not supported by this
      installer script (yet - PRs welcome! [hack/install.sh]), or does not yet have
      a package for Docker.  Please visit the following URL for more detailed
      installation instructions:

        https://docs.docker.com/engine/installation/

    EOF
    exit 1
}

# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
if [ ! -z $1 ] ; then docker_version=$1; fi

do_install
 

 

posted on 2018-05-13 15:34  flyoss  阅读(351)  评论(0编辑  收藏  举报

导航