Docker是一个跨平台的轻量级容器,可移植性非常高,一次部署,终生可用。网上这方面的概述一大堆,就不细写了。这一套搭建下来,其实就是Docker镜像、Registry仓库、Docker容器。我们可以在本地自己生产镜像(下面会有具体操作),也可以直接下载别人或者官方的现成镜像,然后pull到Registry仓库(文中使用DockerHub(https://hub.docker.com/)是默认的 Registry,由 Docker 公司维护,上面有数以万计的镜像,用户可以自由下载和使用。)。这个时候我们可以在任何地方安装了Docker的地方push我们的镜像,build and run.....
腾讯云安装Docker
先登录腾讯云后台,可以直接登录后台,也可以用本地终端
ssh ubuntu@ip地址 //注意腾讯云用户名是ubuntu,不是root再输入密码即可~
先登录腾讯云后台.png
使用
sudo passwd root
设置root的密码切换到root用户
ubuntu@VM-42-54-ubuntu:~$ su rootPassword: root@VM-42-54-ubuntu:/home/ubuntu#
在服务器下载Docker
官方安装指南
1.更新apt软件包索引。 $ sudo apt-get update2.安装最新版本的Docker CE,或转到下一步安装特定版本。任何现有的Docker安装都会被替换。 $ sudo apt-get install docker-ce
在这里我遇到了错误E: Unable to locate package docker-ce
有人在stack overflow给出答案
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"sudo apt-get update sudo apt-get install docker-ce
检测安装成功了没
root@VM-42-54-ubuntu:/home/ubuntu# docker versionClient: Version: 17.12.1-ce API version: 1.35 Go version: go1.9.4 Git commit: 7390fc6 Built: Tue Feb 27 22:17:40 2018 OS/Arch: linux/amd64Server: Engine: Version: 17.12.1-ce API version: 1.35 (minimum version 1.12) Go version: go1.9.4 Git commit: 7390fc6 Built: Tue Feb 27 22:16:13 2018 OS/Arch: linux/amd64 Experimental: false
服务器Docker安装完毕~
Mac端安装Docker
官方下载地址谁用谁知道,整整下了我一下午!!!
百度云:链接:https://pan.baidu.com/s/1ppYSk24VfhUGS3XLHe4hZw 密码:9uly
根据晚上资料发现以前好像是使用了boot2docker或者docker toolbox。但现在docker for Mac全搞定了,也就不去查看以前的一些工具了。一键安装完毕后打开,右上角小鲸鱼出现了
小鲸鱼.png
打开终端:
localhost:~ ljb48229$ docker versionClient: Version: 17.12.0-ce API version: 1.35 Go version: go1.9.2 Git commit: c97c6d6 Built: Wed Dec 27 20:03:51 2017 OS/Arch: darwin/amd64Server: Engine: Version: 17.12.0-ce API version: 1.35 (minimum version 1.12) Go version: go1.9.2 Git commit: c97c6d6 Built: Wed Dec 27 20:12:29 2017 OS/Arch: linux/amd64 Experimental: true
本地安装完毕~
注册Docker hub
官网注册自己的Docker ID
用来存放自己的镜像~
开始玩Docker
先在本地生成一个镜像,在pull到Dockerhub,然后在服务器push这个镜像,运行~
在本地列出已经下载下来的镜像,可以使用 docker images 命令。
localhost:~ ljb48229$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE
可以看到现在本地的镜像没有。
现在将firstwenapp包打包成镜像~
image.png
在main.go文件中
package mainimport ( "fmt" "net/http")func handler(rw http.ResponseWriter, req *http.Request) { fmt.Fprintf(rw, "hello world, %s", req.URL.Path[1:]) }func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
监听8080端口,访问时返回hello world + 请求参数
,功能很简单~
可以看到我们在项目根目录下增加了Dockerfile文件。
Dockerfile文件
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
FROM golang ADD . $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp WORKDIR $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp RUN go install github.com/jiangboLee/go_web_study/firstwebapp ENTRYPOINT /go/bin/firstwebapp EXPOSE 8080
FROM 指定基础镜像
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。而 FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。这里是指定golang的环境。
ADD
如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
在 Docker 官方的最佳实践文档中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。
另外需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
WORKDIR 指定工作目录
格式为WORKDIR <工作目录路径>
。
使用WORKDIR
指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR
会帮你建立目录。
之前提到一些初学者常犯的错误是把 Dockerfile 等同于 Shell 脚本来书写,这种错误的理解还可能会导致出现下面这样的错误:
RUN cd /app RUN echo "hello" > world.txt
如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /app/world.txt
文件,或者其内容不是hello
。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN
命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dokerfile 构建分层存储的概念不了解所导致的错误。
每一个 RUN
都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /app
的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR
指令。
RUN 执行命令
RUN
指令是用来执行命令行命令的。由于命令行的强大能力,RUN
指令在定制镜像时是最常用的指令之一。其格式有两种:
shell 格式:RUN <命令>
,就像直接在命令行中输入的命令一样。刚才写的 Dockrfile 中的 RUN 指令就是这种格式。RUN go install github.com/jiangboLee/go_web_study/firstwebapp
exec 格式:RUN ["可执行文件", "参数1", "参数2"]
,这更像是函数调用中的格式。
既然 RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每一层构建需要的命令写出来,比如这样:
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
仅仅使用一个 RUN
指令,并使用&&
将各个所需命令串联起来。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。
并且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \
的命令换行方式,以及行首#
进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。
此外,还可以看到这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。
很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。
ENTRYPOINT
ENTRYPOINT
命令指令指示/go/bin/firestwebapp
设置为随容器启动
EXPOSE声明端口
EXPOSE
指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P
时,会自动随机映射 EXPOSE
的端口。
要将 EXPOSE
和在运行时使用 -p <宿主端口>:<容器端口>
区分开来。-p
,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE
仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
更多指令参考
开始构建镜像
docker build -t firstwebapp .
localhost:firstwebapp ljb48229$ docker build -t firstwebapp . Sending build context to Docker daemon 3.072kB Step 1/6 : FROM golang latest: Pulling from library/golang3e731ddb7fc9: Downloading [===============> ] 13.67MB/45.13MB47cafa6a79d0: Download complete 79fcf5a213c7: Downloading [==================================> ] 2.961MB/4.335MB68e99216b7ad: Waiting 9fc7abc9c77e: Waiting ba4ddae991a2: Waiting 3f3987c89b39: Waiting
会比较慢,耐心等吧。也可以使用DaoCloud注册后找到
DaoCloud.png
里面3个平台的加速都有,下方怎么配置也很清楚。
构建结束后可在本地运行
localhost:firstwebapp ljb48229$ docker build -t firstwebapp . Sending build context to Docker daemon 3.072kB Step 1/6 : FROM golanglatest: Pulling from library/golang3e731ddb7fc9: Pull complete 47cafa6a79d0: Pull complete 79fcf5a213c7: Pull complete 68e99216b7ad: Pull complete 9fc7abc9c77e: Pull complete ba4ddae991a2: Pull complete 3f3987c89b39: Pull complete Digest: sha256:6eb41fbcc928d0ddbd1099c6dca11ba4e4055ce8392292c0340bf06471a42f8eStatus: Downloaded newer image for golang:latest ---> 1c1309ff8e0d Step 2/6 : ADD . $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp ---> 6bf65c3822b6 Step 3/6 : WORKDIR $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp Removing intermediate container 6189eea41a54 ---> 7c7b58c22b69 Step 4/6 : RUN go install github.com/jiangboLee/go_web_study/firstwebapp ---> Running in e22c727c8817 Removing intermediate container e22c727c8817 ---> 3f7f25083caa Step 5/6 : ENTRYPOINT /go/bin/firstwebapp ---> Running in 0691889223e9 Removing intermediate container 0691889223e9 ---> ef2d999edd12 Step 6/6 : EXPOSE 8080 ---> Running in ed2b63c75d71 Removing intermediate container ed2b63c75d71 ---> ef66341d11f1 Successfully built ef66341d11f1 Successfully tagged firstwebapp:latestlocalhost:firstwebapp ljb48229$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE firstwebapp latest ef66341d11f1 11 seconds ago 786MB golang latest 1c1309ff8e0d 3 weeks ago 779MBlocalhost:firstwebapp ljb48229$ docker run -p 80:8080 --rm firstwebapp
这时候打开浏览器http://localhost/ljb,效果如下:
image.png
-p 80:8080
标志打开HTTP端口80并将其映射至前面通过EXPOSE命令暴露的8080端口,而--rm标志则指示Docker在容器已经存在的情况下,先移除已有的容器,然后再创建并启动新容器。
localhost:~ ljb48229$ docker ps //查看已启动容器CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES363e265c7e66 firstwebapp "/bin/sh -c /go/bin/…" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp suspicious_joliot localhost:~ ljb48229$ docker stop 363e265c7e66 //关闭容器363e265c7e66 localhost:~ ljb48229$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES localhost:~ ljb48229$
将镜像上传
docker login docker push 注册用户名/镜像名
再去登录自己的dockerHub,就能看到上传的镜像~
参考
服务器拉去镜像
docker pull 注册用户名/镜像名
然后运行docker run -p 80:8080 --rm firstwebapp
这个时候只需要在浏览器输入您的ip地址就会有hello world
结束
这个流程大概已经走了一遍。接下来就是丰富代码,然后构建新的镜像,推,拉~就是这么简单 ~可能更高级的用法值得探索哈 ~
作者:iOS小白白
链接:https://www.jianshu.com/p/ea3078dae4fb