Ubuntu 下的 Docker 安装与使用
目录
Docker 安装
为什么想到使用 Docker 呢?是因为 Docker 能够提供给我一个相对比较干净的系统而不需要关心宿主机到底多么杂乱(我这么做真的是因为我的宿主机太乱了,各种复杂的依赖和操蛋的资源共享方式)。首先需要安装一个 Docker 的服务程序,我的宿主机是 UbuntuKylin,直接通过 Docker 的官方安装手册安装即可。
[jackieliu@localhost ~]$ sudo apt-get remove docker docker-engine docker.io containerd runc
[jackieliu@localhost ~]$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
添加 Docker 的官方源地址,因为我的宿主机是 ARM64 的服务器,所以需要选择 ARM64 的源地址,如果你所使用的宿主机是 x86 的,这个地方就需要更改为 [arch=amd64]
,实在搞不懂就去看看上面我给的官方安装手册地址。
[jackieliu@localhost ~]$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
[jackieliu@localhost ~]$ sudo apt-key fingerprint 0EBFCD88
[jackieliu@localhost ~]$ sudo add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
[jackieliu@localhost ~]$ sudo apt-get update
安装他们吧。
[jackieliu@localhost ~]$ sudo apt-get install docker-ce docker-ce-cli containerd.io
Docker 使用
启动 docker 服务
完成了 Docker 的安装之后,接下来启动这个后台的 dockerd 服务,这样 docker 就可以一直为你工作了。
[jackieliu@localhost ~]$ sudo service docker start
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since 五 2019-03-01 11:46:07 CST; 3h 56min ago
Docs: https://docs.docker.com
Main PID: 28483 (dockerd)
Tasks: 37
Memory: 56.3M
CPU: 7.049s
CGroup: /system.slice/docker.service
└─28483 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
有了 docker 的服务,那么就需要开始正式的使用它们了。
拉取镜像
如果你很熟悉代码管理工具 git
,那么你就能够很快的理解 Docker 与 git 非常的相像,只不过一个管理的是代码,而一个管理的是镜像。
首先需要自官方的地址(其他的镜像地址也可)拉取一些各发行版本自行维护的正式镜像,比如 ubuntu 官方维护的 18.04 镜像就是我现在正在使用的一个。
[jackieliu@localhost ~]$ sudo docker pull ubuntu:bionic
由于我没有指定自哪个地址拉取镜像,那么 docker 默认就会从他的官方地址 hub.docker.com 拉取,一般来说各操作系统发行版都会在这里发布自己的 docker 镜像。这里的 ubuntu 是仓库的名称,而 bionic 是所谓的 tag 的名称,docker 都是使用 tag 来标记 version。等待 pull 按成你就已经有了一个 ubuntu18.04 的镜像文件,保存在 docker 自己维护的一个镜像目录,使用查看命令来查看当前的系统存在哪些镜像。
[jackieliu@localhost ~]$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
debian latest bcfa7c31af42 11 days ago 1.26GB
jackieliu1/ubuntu18.04-jk latest cd27df063a12 2 weeks ago 951MB
debian buster-20190204 dfdbfb4efa07 3 weeks ago 108MB
ubuntu xenial ee5e81436e6e 5 weeks ago 108MB
jackieliu1/ubuntu18.04-jk v4 946608869d8c 6 weeks ago 757MB
上面就是我的机器上的拉取到的一些镜像信息,如果只拉取了一个就只会有一条信息。
启动镜像
准备好了镜像接下来就需要启动这个镜像,-i
表示持续打开 STDIN(标准输入),这样才可以让你输入信息,不然这样的 docker 镜像虽然启动但是你没办法直接用;-t
表示申请一个 tty 给这个 docker 使用,同样是为了能够交互,所以一般情况下都是一起使用,最后跟着的 bash
表示启动这个镜像里面的一个程序,自然可以是镜像内部的任意程序,这里填写的是 bash 是为了我们能够操作这个镜像,所以需要进入 bash,等这一条命令执行成功就会进入到镜像内部的 bash 环境,下面显示的那个控制台就是镜像内部的终端,恭喜你已经成功的进入 Docker 镜像内部,此时你已经得到了一个容器,6d1d7322d53b
就是这个容器的 ID。引入了一个新概念就是容器,其实容器就是镜像运行起来的一个状态,但是一个镜像可以不停的被运行,所以就是一个一对多的过程。
[jackieliu@localhost ~]$ sudo docker run -it ubuntu:bionic bash
root@6d1d7322d53b:/#
后台运行
通过上面的命令可以从镜像启动一个容器,但是在退出终端之后容器也就自动退出了,很多时候我们需要一种可以常驻于后台的服务而不是需要随时保持前端输入。要做到后台运行也很简单,只需要在上一条命令的基础上添加 -d
参数即可。
[jackieliu@localhost ~]$ sudo docker run -itd ubuntu:bionic bash
查看容器
在执行镜像实例化为容器之后,需要查看当前正在运行的容器以及所有系统中存在的容器。很类似于查看系统的进程命令 ps
,查看当前系统正在运行的容器如下:
[jackieliu@localhost ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9da8f631e07c debian:latest "bash" 45 seconds ago Up 42 seconds sharp_banach
要查看所有的容器命令只需要在上一条命令之后添加 -a
即可,这样也可以看到所有的容器,包括当前没有在运行的容器。
[jackieliu@localhost ~]$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
685b5ee2c60b ubuntu:xenial "bash" 20 seconds ago Exited (0) 7 seconds ago nifty_engelbart
9da8f631e07c debian:latest "bash" 49 seconds ago Up 46 seconds sharp_banach
镜像实例化运行为容器之后,是不会被删除的,他可以重复的启动和停止,除非主动删除,所以只要启动过一次当前的容器即便重新启动物理主机,之前的容器仍然存在于系统之中,可以被 docker ps -a
命令查看得到。
进入后台容器
容器进入后台之后无法直接在终端与之进行交互,所以我们可以通过别的手段再次进入容器内部,当然可以通过转发 ssh 协议端口的方式进行交互,但是官方推荐的方式通过 exec
命令再次进入容器:
[jackieliu@localhost ~]$ sudo docker exec -it 685b5ee2c60b bash
root@685b5ee2c60b:/#
删除容器
容器可以被创建(镜像启动就会自动创建一个独一无二的容器),那么自然也可以被删除,有些时候我们需要只进行一次任务之后自动删除这个容器,这样可以避免资源浪费,这对临时任务或者一次性任务很有好处,不然系统中会存在很多个临时容器1。要实现这个也很简单,只需要在启动容器的时候添加 --rm
参数即可,那么在当前容器任务完成退出之后,这个容器会被后台服务自动删除。
[jackieliu@localhost ~]$ sudo docker run -it --rm ubuntu:xenial ls
bin dev home media opt root sbin sys usr
boot etc lib mnt proc run srv tmp var
上面的命令我使用 ls 来查看 docker 镜像内部的根目录下的文件,当 ls 执行完毕之后,容器就会被退出,这个时候 docker ps -a
是查询不到这个容器的。除了在创建的时候可以删除容器,也可以在启动之后手动删除容器。
[jackieliu@localhost ~]$ sudo docker run -it ubuntu:xenial ls
bin dev home media opt root sbin sys usr
boot etc lib mnt proc run srv tmp var
[jackieliu@localhost ~]$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26b90a2a5e3c ubuntu:xenial "ls" 6 seconds ago Exited (0) 4 seconds ago trusting_varahamihira
685b5ee2c60b ubuntu:xenial "bash" 23 minutes ago Exited (0) 23 minutes ago nifty_engelbart
9da8f631e07c debian:latest "bash" 24 minutes ago Up 24 minutes sharp_banach
[jackieliu@localhost ~]$ sudo docker rm 26b90a2a5e3c
26b90a2a5e3c
[jackieliu@localhost ~]$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
685b5ee2c60b ubuntu:xenial "bash" 24 minutes ago Exited (0) 24 minutes ago nifty_engelbart
9da8f631e07c debian:latest "bash" 24 minutes ago Up 24 minutes sharp_banach
可以看到手动删除之后,就查看不到容器存在。
启动与停止容器
容器被创建之后,除非使用 --rm
否则并不会被删除,所以存在被再次启动的能力,这种能力使得容器可以被重复利用。既然可以再次启动就能被停止,命令如下:
[jackieliu@localhost ~]$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
685b5ee2c60b ubuntu:xenial "bash" About an hour ago Exited (0) About an hour ago nifty_engelbart
9da8f631e07c debian:latest "bash" About an hour ago Up About an hour sharp_banach
[jackieliu@localhost ~]$ sudo docker start 685b5ee2c60b
685b5ee2c60b
[jackieliu@localhost ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
685b5ee2c60b ubuntu:xenial "bash" About an hour ago Up 8 seconds nifty_engelbart
9da8f631e07c debian:latest "bash" About an hour ago Up About an hour sharp_banach
[jackieliu@localhost ~]$ sudo docker stop 685b5ee2c60b
685b5ee2c60b
需要注意的是,使用 start 启动的容器会进入后台运行状态。
共享目录
很多时候,docker 需要与宿主机进行文件共享,那么通过目录共享的方式是一种比较便捷的方式,只需要通过 -v
来进行指定即可。
[jackieliu@localhost ~]$ sudo docker run -itd -v `pwd`:/data ubuntu:xenial bash 9ca46973514553e0cb8e898a659354ebadc08209aea40405edf4531aa11dd9e1
[jackieliu@localhost ~]$ sudo docker exec -it 9ca469735145 bash
root@9ca469735145:/# ls /data/
aarch64_tsc dump linux-base_4.5kord2.dsc
可以看到,通过 exec
进入到容器之后,查看 /data 目录就可以看到当前目录的信息,表示共享已经成功。
Docker 高级
提交本地镜像修改
除了官方的镜像之外,大部分时候我们需要对镜像进行定制,比如安装自己的服务或者安装其他的辅助软件等等,但这些操作都是在容器内部完成的,并不属于镜像,容器一旦被删除,那么这些修改就不存在了,而且针对容器的修改只影响当前容器,如果再次从镜像启动一个容器,这些修改使不会被继承到新启动的容器,所以我们需要将对当前容器的修改提交到本地镜像,其实这些都很简单,就如同使用 git 提交补丁一样的提交这些修改即可。
[jackieliu@localhost ~]$ sudo docker commit -a "Jackie Liu" -m "hello commit" 9ca469735145
本地已经完成修改并提交,如果你已经完成一系列的修改,那么你就可以形成一个 tag 来表示一个 release 版本。
[jackieliu@localhost ~]$ sudo docker tag ubuntu:xenial ubuntu:mytag-v1
推送到远程仓库
当你在本地拥有了提交的 tag,你可以把他推送到远端服务器上,让 dockerhub 服务帮你储存你的镜像文件(不是运行的服务容器,只是镜像文件),这样你就可以在另外的机器上通过 docker pull
下载下来继续修改或者运行。docker 命令的默认远程地址是 hub.docker.com,当然你也可以自己来搭建这样的服务,目前这不是我考虑的范围,毕竟 dockerhub 上提供一个免费的私密仓库和无数的公开仓库给每一个账户,对我来说太足够了,真的很人性化。譬如我要提交刚刚我做的 tag,命令如下。
[jackieliu@localhost ~]$ sudo docker push jackieliu1/ubuntu:mytag-v1
这里的 jackieliu1 是我在 hub.docker.com 上的账户名称,如果你也需要提交到远端服务器,那么自己去申请一个账号,创建仓库即可。
- 我个人的内核编译机系统就是用的 docker,所以每一次任务都是一个单独的任务,那么就必须在运行完毕之后自动删除掉这个容器。 ↩︎