@toc
1 虚拟机和容器相关概念说明
1.1 虚拟机
虚拟可以解决环境配置方面的一些麻烦,但是虚拟机也有很多的缺点:
- 资源占用多:虚拟机会单独占用一部分内存和硬盘空间,其他程序不能够使用这些资源,即使虚拟机里的应用程序使用的内存只有1MB,虚拟机依然需要几百MB内存才能运行
- 冗余步骤多
- 启动慢
1.2 Linux容器:
由于虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离
。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。
由于容器是进程级别的,相比虚拟机有很多优势。
- 启动快
- 资源占用少
- 体积小:容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
总之,容器
有点像轻量级的虚拟机
,能够提供虚拟化的环境
,但是成本开销小得多
。
1.3 Docker 是什么?
Docker
属于 Linux 容器
的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
Docker 将应用程序
与该程序的依赖
,打包在一个文件里面
。运行这个文件,就会生成一个虚拟容器
。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器
还可以进行版本管理
、复制
、分享
、修改
,就像管理普通的代码一样。
1.4 Docker 的用途
Docker 的主要用途,目前有三大类。
(1)提供一次性的环境
。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
(2)提供弹性的云服务
。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
(3)组建微服务架构
。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。
2 docker的安装、添加用户组和启动
2.1 docker在不同系统中的安装
2.2 验证docker是否安装成功的命令
docker version
或docker info
2.3 把docker添加到用户组中
Docker
需要用户具有sudo 权限
,为了避免每次使用docker命令都输入sudo,可以把用户加入 Docker 用户组(官方文档)
sudo usermod -aG docker $USER
2.4 启动docker
Docker 是服务器----客户端架构。命令行运行docker命令的时候,需要本机有 Docker 服务。如果这项服务没有启动,可以用下面的命令启动(官方文档)。
service 命令的用法
sudo service docker start
systemctl 命令的用法
sudo systemctl start docker
3 image文件(镜像文件)
1、Docker的镜像文件
Docker
把应用程序
及其依赖
,打包在 image 文件
里面。只有通过这个文件
,才能生成 Docker 容器
。image 文件可以看作是容器的模板
。Docker 根据 image 文件
生成容器的实例
。同一个 image 文件,可以生成多个同时运行的容器实例。
image 是二进制文件
。实际开发中,一个 image 文件往往通过继承另一个 image 文件
,加上一些个性化设置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image。
注意:
image镜像
创建的实例
叫container容器
,因此,同一个image文件
可以生成多个同时运行的容器
,容器可以删除,并不会把镜像删除!
2、列出本机的所有镜像文件
docker image ls
或docker images
3、删除 image 文件
docker image rm [imageName]
image 文件
是通用的
,一台机器的 image 文件拷贝到另一台机器,照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件
,而不是自己制作。即使要定制,也应该基于别人的 image 文件进行加工
,而不是从零开始制作。
为了方便共享,image 文件制作完成后,可以上传到网上的仓库。Docker 的官方仓库Docker Hub 是最重要、最常用的 image 仓库。此外,出售自己制作的 image 文件也是可以的。
4 实例:hello-world镜像
4.1 查看和删除本地已经有的镜像
1、查看本机当前有哪些镜像:
docker image ls
(base) shl@zhihui-mint:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> c3c7ef3f55e6 2 months ago 6.76GB
nvcr.io/nvidia/tensorrt 20.09-py3 b1386993f571 5 months ago 5.75GB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
(base) shl@zhihui-mint:~$
由于,我们要演示hello-world
镜像,我们先删除它
2、删除镜像
docker rm imageName
如下,我们删除hello-world镜像
(base) shl@zhihui-mint:~$ docker image rm hello-world
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container b9f6617d1ee5 is using its referenced image bf756fb1ae65
(base) shl@zhihui-mint:~$
4.2 删除镜像的时候报错:Error response from daemon: conflict: unable to remove repository reference
删除的时候报错了,我们看到说hello-world
镜像,依赖b9f6617d1ee5
容器,因此,如果要删除hello-world
镜像需要先删除这个依赖的b9f6617d1ee5
容器
1、删除镜像依赖的容器
(base) shl@zhihui-mint:~$ docker rm b9f6617d1ee5
b9f6617d1ee5
(base) shl@zhihui-mint:~$
依赖的容器可能不只一个,如果有多个,用同样的方法删除!
2、之后再删除指定名子的image镜像,即可:
docker image rm hello-world
也可以指定镜像的版本号:
docker image rm hello-world:latest
3、具体删除过程如下
(base) shl@zhihui-mint:~$ docker image rm hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec
Untagged: hello-world@sha256:8c5aeeb6a5f3ba4883347d3747a7249f491766ca1caa47e5da5dfcf6b9b717c0
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b
Deleted: sha256:9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63
(base) shl@zhihui-mint:~$
4、再次查看,此时hello-world镜像已经被删除
(base) shl@zhihui-mint:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> c3c7ef3f55e6 2 months ago 6.76GB
nvcr.io/nvidia/tensorrt 20.09-py3 b1386993f571 5 months ago 5.75GB
(base) shl@zhihui-mint:~$
参考:删除镜像依赖的容器
4.3 列出所有的容器
1、 列出所有运行或没有运行的容器 docker ps -a
docker ps -a
(base) shl@zhihui-mint:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc0d85ad579f c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago fervent_solomon
fb290564f3f7 c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago gracious_tu
c82060ce8175 c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago silly_volhard
0ecdbc939f4b c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago confident_nash
e389c1150a0f c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago sweet_rhodes
a1985afa6eeb c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago dazzling_bardeen
97de8f36fbb2 c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago confident_chaum
259c012fd055 c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago fervent_bardeen
a9a1d44d0bee c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago flamboyant_benz
fa9df3e92577 c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago beautiful_zhukovsky
fc329df9dcf3 03b55962b0b5 "/bin/sh -c 'wget ht…" 2 months ago Exited (9) 2 months ago busy_bassi
(base) shl@zhihui-mint:~$
2、停止所有的容器
停止container,这样才能够删除其中的images:
,停止所有的容器:
docker stop $(docker ps -a -q)
(base) shl@zhihui-mint:~$ docker stop $(docker ps -a -q)
dc0d85ad579f
fb290564f3f7
c82060ce8175
0ecdbc939f4b
e389c1150a0f
a1985afa6eeb
97de8f36fbb2
259c012fd055
a9a1d44d0bee
fa9df3e92577
fc329df9dcf3
(base) shl@zhihui-mint:~$
3、删除所有的容器
如果想要删除所有container的话再加一个指令 ,狠心把容器都删除掉了,因为光停止还是不能删除镜像。
docker rm $(docker ps -a -q)
4、删除对应的image 镜像
相关容器关闭后,删除对应的images,通过image的id来指定删除谁
docker rmi ID
或 `docker image rm [imageName]
要删除全部image的话
docker rmi $(docker images -q)
4.4 把docker的镜像源换成国内镜像源
由于,下面用到的hello-world
会到官网下载,但是速度比较慢,因此我们可以通过把镜像源改为国内的
,提高镜像下载的速度!
我在Ubuntu18.04配置docker国内镜像源如下(参考):
1、创建一个/etc/docker/daemon.json
文件,我的该目录下没有daemon.json
文件:
sudo vim /etc/docker/daemon.json
2、添加如下内容:
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
3、重启docker服务
sudo service docker restart
4、使用下面的命令查看是否生效
docker info|grep Mirrors -A 1
5、输出如下信息,则表示配置成功,再次docker pull速度就会很快了!
(base) shl@zhihui-mint:~$ docker info|grep Mirrors -A 1
WARNING: No swap limit support
(base) shl@zhihui-mint:~$ sudo vim /etc/docker/daemon.json
(base) shl@zhihui-mint:~$ service docker restart
(base) shl@zhihui-mint:~$ docker info|grep Mirrors -A 1
WARNING: No swap limit support
Registry Mirrors:
https://docker.mirrors.ustc.edu.cn/
(base) shl@zhihui-mint:~$
4.5 实例:hello-world镜像
下面,我们通过最简单的 image 文件"hello world",感受一下 Docker。
1、将hello-world
的 image 文件从仓库抓取到本地
。
docker image pull library/hello-world
(base) shl@zhihui-mint:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> c3c7ef3f55e6 2 months ago 6.76GB
nvcr.io/nvidia/tensorrt 20.09-py3 b1386993f571 5 months ago 5.75GB
(base) shl@zhihui-mint:~$
(base) shl@zhihui-mint:~$ docker image pull library/hello-world
Using default tag: latest
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:7e02330c713f93b1d3e4c5003350d0dbe215ca269dd1d84a4abc577908344b30
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
(base) shl@zhihui-mint:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> c3c7ef3f55e6 2 months ago 6.76GB
nvcr.io/nvidia/tensorrt 20.09-py3 b1386993f571 5 months ago 5.75GB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
(base) shl@zhihui-mint:~$
上面代码中,docker image pull
是抓取 image 文件的命令。library/hello-world
是image 文件
在仓库里面的位置
,其中library
是 image 文件所在的组
,hello-world
是 image 文件的名字
。
由于 Docker 官方提供的 image 文件,都放在library组里面,所以它的是默认组,可以省略
。因此,上面的命令可以写成下面这样。
docker image pull hello-world
2、先查看一下当前有没有运行的container容器:
docker container ls
或docker ps
列出当前运行的容器:
(base) shl@zhihui-mint:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(base) shl@zhihui-mint:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(base) shl@zhihui-mint:~$
3、从hello-world镜像生成一个容器,并运行它
docker container run hello-world
运行hello-world镜像文件,其实就是从这个image生成一个container容器实例:
docker container run
命令会从image 文件
,生成一个正在运行的容器实例
。
注意,docker container run
命令具有自动抓取 image 文件
的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的docker image pull命令并不是必需的步骤。
如果运行成功,输出如下信息:
(base) shl@zhihui-mint:~$ docker container run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
(base) shl@zhihui-mint:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(base) shl@zhihui-mint:~$ docker ps
输出这段提示以后,hello world
就会停止运行
,容器自动终止
。因此我们查看的哪些正在运行的容器时,hello-world生成的容器已经终止!
4、如果想要列出所有的容器,包括已经终止的容器:
docker container ls -a
(base) shl@zhihui-mint:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d93acb74ecfe hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago charming_jang
(base) shl@zhihui-mint:~$
有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统。
docker container run -it ubuntu bash
对于那些不会自动终止的容器,必须使用docker container kill 命令手动终止。
docker container kill [containID]
5 container容器文件:
image 文件
生成的容器实例
,本身也是一个文件
,称为容器文件
。也就是说,一旦容器生成,就会同时存在两个文件:image 文件
和容器文件
。而且关闭容器并不会删除容器文件
,只是容器停止运行而已
。
1、列出本机正在运行的容器
docker container ls
或docker ps
2、列出本机所有容器,包括终止运行的容器
docker container ls --all
上面命令的输出结果之中,包括容器的 ID。很多地方都需要提供这个 ID,比如上一节终止容器运行的docker container kill命令。
3、删除容器文件
终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm命令删除。
docker container rm [containerID]
(base) shl@zhihui-mint:~$ docker container ls -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6294aa75c40 hello-world "/hello" 29 minutes ago Exited (0) 29 minutes ago nice_dirac
(base) shl@zhihui-mint:~$ docker container rm f6294aa75c40
f6294aa75c40
(base) shl@zhihui-mint:~$ docker container ls -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc0d85ad579f c3c7ef3f55e6 "/bin/sh -c 'cmake …" 2 months ago Exited (2) 2 months ago fervent_solomon
(base) shl@zhihui-mint:~$
6 Dockerfile文件
学会使用 image 文件
以后,接下来的问题就是,如何可以生成 image 文件?
如果你要推广自己的软件,势必要自己制作 image 文件。
这就需要用到 Dockerfile 文件
。它是一个文本文件
,用来配置 image
。Docker 根据 该文件生成二进制的 image 文件
。
下面通过一个实例,演示如何编写 Dockerfile 文件。
7 实例:制作自己的 Docker 容器
7.1 准备工作
7.1.1 克隆代码
下面我以 koa-demos 项目为例,介绍怎么写 Dockerfile 文件,实现让用户在 Docker 容器里面运行 Koa 框架。
作为准备工作,请先下载源码。
$ git clone https://github.com/ruanyf/koa-demos.git
$ cd koa-demos
7.1.2 安装npm工具
由于下面编写的Dockerfile文件
中会用到npm命令
,因此我们需要先安装一下:
在build建立之前,需要先安装npm:
1、在Ubuntu18.04上安装npm参考:https://blog.csdn.net/wangtaoking1/article/details/78005038
(base) shl@zhihui-mint:~/koa-demos$ sudo apt install nodejs-dev
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
您也许需要运行“apt --fix-broken install”来修正上面的错误。
下列软件包有未满足的依赖关系:
nodejs-dev : 依赖: libssl1.0-dev (>= 1.0.2) 但是它将不会被安装
依赖: libuv1-dev (>= 1.15.0) 但是它将不会被安装
依赖: nodejs (= 8.10.0~dfsg-2ubuntu0.4) 但是它将不会被安装
ros-melodic-librviz-tutorial : 依赖: ros-melodic-rviz 但是它将不会被安装
ros-melodic-pluginlib : 依赖: ros-melodic-class-loader 但是它将不会被安装
ros-melodic-rqt-rviz : 依赖: ros-melodic-rviz 但是它将不会被安装
ros-melodic-rviz-plugin-tutorials : 依赖: ros-melodic-rviz 但是它将不会被安装
ros-melodic-rviz-python-tutorial : 依赖: ros-melodic-rviz 但是它将不会被安装
E: 有未能满足的依赖关系。请尝试不指明软件包的名字来运行“apt --fix-broken install”(也可以指定一个解决办法)。
(base) shl@zhihui-mint:~/koa-demos$ sudo apt --fix-broken install
先修正上面的错误:sudo apt install --fix-broken
2、安装好npm之后,做好准备工作:
(base) shl@zhihui-mint:~/koa-demos$ node -v
v8.17.0
(base) shl@zhihui-mint:~/koa-demos$ npm -v
6.13.4
(base) shl@zhihui-mint:~/koa-demos$ du --max-depth=1 -h
832K ./.git
92K ./demos
996K .
(base) shl@zhihui-mint:~/koa-demos$ ls
demos Dockerfile logo.png package.json package-lock.json README.md
(base) shl@zhihui-mint:~/koa-demos$
7.2 编写Dockerfile文件
1、首先,在项目的根目录下,新建一个文本文件.dockerignore
,写入下面的内容。
.git
node_modules
npm-debug.log
上面代码表示,这三个路径要排除,不要打包进入 image 文件
。如果你没有路径要排除,这个文件可以不新建。
2、然后,在项目的根目录下,新建一个文本文件Dockerfile
,写入下面的内容。
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
上面代码一共五行,含义如下。
FROM node:8.4
:该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node。COPY . /app
:将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录。WORKDIR /app
:指定接下来的工作路径为/app。RUN npm install
:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。EXPOSE 3000
:将容器 3000 端口暴露出来, 允许外部连接这个端口。
7.3 创建 image 文件
有了 Dockerfile 文件以后,就可以使用docker image build
命令创建 image 文件
了。
docker image build -t koa-demo .
# 或者
docker image build -t koa-demo:0.0.1 .
上面代码中,-t
参数用来指定image 文件
的名字
,后面还可以用冒号指定标签。如果不指定,默认的标签
就是latest
。最后的那个点
表示 Dockerfile 文件所在的路径
,上例是当前路径,所以是一个点。
如果运行成功,就可以看到新生成的 image 文件koa-demo了。
(base) shl@zhihui-mint:~/koa-demos$ docker image build -t koa-demo .
Sending build context to Docker daemon 318kB
Step 1/5 : FROM node:8.4
---> 386940f92d24
Step 2/5 : COPY . /app
---> Using cache
---> c1a000787102
Step 3/5 : WORKDIR /app
---> Using cache
---> 27f49f07b13c
Step 4/5 : RUN ["npm", "install"]
---> Using cache
---> 8b827c8f4fa2
Step 5/5 : EXPOSE 3000/tcp
---> Using cache
---> 550298705df4
Successfully built 550298705df4
Successfully tagged koa-demo:latest
(base) shl@zhihui-mint:~/koa-demos$
可以看出,build建立镜像文件的步骤
,就是执行我们编写的Dockerfile
文件中内容的步骤!
docker image ls
base) shl@zhihui-mint:~/koa-demos$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
koa-demo latest 550298705df4 20 minutes ago 676MB
<none> <none> c3c7ef3f55e6 2 months ago 6.76GB
nvcr.io/nvidia/tensorrt 20.09-py3 b1386993f571 5 months ago 5.75GB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
node 8.4 386940f92d24 3 years ago 673MB
(base) shl@zhihui-mint:~/koa-demos$
7.4 生成容器
1、docker container run
命令会从 image 文件
生成容器。
docker container run -p 8000:3000 -it koa-demo /bin/bash
# 或者
docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
# 也可以通过-v参数,把本地的路径映射到docker容器中的目录,这样当容器被删除的时候,保存到本地的路径中的文件也不会被删除
# docker container run -p 8000:3000 -v /home/shl/shl_res/3_data/Aachen-Day-Night:/app -it koa-demo /bin/bash
上面命令的各个参数含义如下:
-p参数
:容器
的3000 端口
映射到本机
的8000 端口
。-it参数
:容器的 Shell
映射到当前的 Shell
,然后你在本机窗口输入的命令,就会传入容器。koa-demo:0.0.1
:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。/bin/bash
:容器启动以后,内部第一个执行的命令
。这里是启动 Bash,保证用户可以使用 Shell。
如果一切正常,运行上面的命令以后,就会返回一个命令行提示符。
运行结果如下:
(base) shl@zhihui-mint:~/koa-demos$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(base) shl@zhihui-mint:~/koa-demos$ docker container run -p 8000:3000 -it koa-demo /bin/bash
root@50eeaecac940:/app# ls
Dockerfile README.md demos logo.png node_modules package-lock.json package.json
root@50eeaecac940:/app#
这表示你已经在容器里面
了,返回的提示符就是容器内部的 Shell 提示符
,50eeaecac940
是容器的ID
。
2、此时启动的容器,就相当于是一个微核的linux:
root@50eeaecac940:/app# ls
Dockerfile README.md demos logo.png node_modules package-lock.json package.json
root@50eeaecac940:/app# cd /home/
root@50eeaecac940:/home# ls
node
root@50eeaecac940:/home# apt -h
apt 1.0.9.8.4 for amd64 compiled on Dec 11 2016 09:48:19
Usage: apt [options] command
CLI for apt.
Basic commands:
list - list packages based on package names
search - search in package descriptions
show - show package details
update - update list of available packages
install - install packages
remove - remove packages
upgrade - upgrade the system by installing/upgrading packages
full-upgrade - upgrade the system by removing/installing/upgrading packages
edit-sources - edit the source information file
root@50eeaecac940:/home#
3、此时你再打开一个终端,就可以查看到正在运行的容器:
(base) shl@zhihui-mint:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50eeaecac940 koa-demo "/bin/bash" About a minute ago Up About a minute 0.0.0.0:8000->3000/tcp epic_germain
(base) shl@zhihui-mint:~$
4、执行下面的命令。
root@50eeaecac940:/app# node demos/01.js
root@50eeaecac940:/app# ls demos/
01.js 03.js 05.js 07.js 09.js 11.js 13.js 15.js 17.js 19.js 21.js
02.js 04.js 06.js 08.js 10.js 12.js 14.js 16.js 18.js 20.js template.html
root@50eeaecac940:/app# node demos/01.js
这时,Koa 框架已经运行起来了。打开本机的浏览器,访问 http://127.0.0.1:8000,网页显示"Not Found",这是因为这个 demo 没有写路由。
你也可以运行其他的js文件,如下是运行:root@50eeaecac940:/app# node demos/02.js
,在浏览器中打开的结果:
这个例子中,Node 进程
运行在Docker 容器的虚拟环境里面
,进程接触到的文件系统
和网络接口
都是虚拟的
,与本机的文件系统和网络接口是隔离的,因此需要定义容器
与物理机
的端口映射(map)
。因为已经将容器的端口3000映射到本机的8000端口,因此只要容器运行,就可以通过本机的8000端口访问到容器的3000端口,从而访问容器的服务!
现在,在容器的命令行,按下 Ctrl + c
停止 Node 进程,然后按下Ctrl + d
(或者输入exit
)退出容器
。此外,也可以用docker container kill
终止容器运行。
在本机的另一个终端窗口,查出容器的 ID
docker container ls
停止指定的容器运行
docker container kill [containerID]
容器停止运行之后,并不会消失,用下面的命令删除容器文件。
查出容器的 ID
$ docker container ls --all
删除指定的容器文件
$ docker container rm [containerID]
也可以使用docker container run命令的--rm参数,在容器终止运行后自动删除容器文件。
$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash
7.5 CMD 命令
上一节的例子里面,容器启动以后,需要手动输入命令node demos/01.js
。我们可以把这个命令写在 Dockerfile
里面,这样容器启动以后,这个命令就已经执行了,不用再手动输入了。
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
CMD node demos/01.js
上面的 Dockerfile 里面,多了最后一行CMD node demos/01.js
,它表示容器启动后自动执行node demos/01.js。
你可能会问,RUN命令与CMD命令的区别在哪里?简单说,RUN命令
在image 文件的构建阶段执行
,执行结果都会打包进入 image 文件;CMD命令
则是在容器启动后执行
。另外,一个 Dockerfile
可以包含多个RUN命令
,但是只能有一个CMD命令
。
注意 :
指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否则它会覆盖CMD命令。现在,启动容器可以使用下面的命令。
docker container run --rm -p 8000:3000 -it koa-demo:0.0.1
7.6 发布 image 文件
容器运行成功后,就确认了 image 文件的有效性。这时,我们就可以考虑把 image 文件分享到网上,让其他人使用。
1、首先,去hub.docker.com
或 cloud.docker.com
注册一个账户。然后,用下面的命令登录
。
docker login
2、接着,为本地的 image 标注用户名和版本。
docker image tag [imageName] [username]/[repository]:[tag]
实例
docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1
也可以不标注用户名,重新构建一下 image 文件。
docker image build -t [username]/[repository]:[tag] .
3 、最后,发布 image 文件。
docker image push [username]/[repository]:[tag]
发布成功以后,登录 hub.docker.com
,就可以看到已经发布的 image 文件
。
8 其他有用的命令
1、docker container start
docker container run
命令是新建容器
,每运行一次,就会新建一个容器。同样的命令运行两次,就会生成两个一模一样的容器文件。如果希望重复使用容器
,就要使用docker container start
命令,它用来启动已经生成、已经停止运行的容器文件。
(base) shl@zhihui-mint:~/test$ docker container kill 50eeaecac940
50eeaecac940
(base) shl@zhihui-mint:~/test$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(base) shl@zhihui-mint:~/test$ docker container start 50eeaecac940
50eeaecac940
(base) shl@zhihui-mint:~/test$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50eeaecac940 koa-demo "/bin/bash" 17 hours ago Up 3 seconds 0.0.0.0:8000->3000/tcp epic_germain
(base) shl@zhihui-mint:~/test$
3、docker container exec
docker container exec
命令用于进入一个正在运行
的 docker 容器
。
docker container exec -it [containerID] /bin/bash
(base) shl@zhihui-mint:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50eeaecac940 koa-demo "/bin/bash" 17 hours ago Up 17 hours 0.0.0.0:8000->3000/tcp epic_germain
(base) shl@zhihui-mint:~$ docker container exec -it 50eeaecac940 /bin/bash
root@50eeaecac940:/app# ls
Dockerfile README.md demos logo.png node_modules package-lock.json package.json
root@50eeaecac940:/app#
在本机上重开启一个终端,进入一个正在运行容器的bash,这种就是使用docker run
的时候没有使用-it
参数的时候,进入正在运行容器的bash!
4、docker container cp
docker container cp
命令用于从正在运行的 Docker 容器
里面,将文件 或 目录拷贝到本机
。
docker container cp [containID]:[/path/to/file] [local-path]
先查看容器中有哪些文件:
root@50eeaecac940:/app# ls
Dockerfile README.md demos logo.png node_modules package-lock.json package.json
root@50eeaecac940:/app# pwd
/app
把容器中的文件或目录拷贝到本机系统中:
(base) shl@zhihui-mint:~/test$ ls
(base) shl@zhihui-mint:~/test$ pwd
/home/shl/test
(base) shl@zhihui-mint:~/test$ docker container cp 50eeaecac940:/app/logo.png /home/shl/test
(base) shl@zhihui-mint:~/test$ ls
logo.png
(base) shl@zhihui-mint:~/test$ docker container cp 50eeaecac940:/app/demos /home/shl/test
(base) shl@zhihui-mint:~/test$ ls
demos logo.png
(base) shl@zhihui-mint:~/test$ ls demos/
01.js 03.js 05.js 07.js 09.js 11.js 13.js 15.js 17.js 19.js 21.js
02.js 04.js 06.js 08.js 10.js 12.js 14.js 16.js 18.js 20.js template.html
(base) shl@zhihui-mint:~/test$
5、把本地文件或目录
拷贝到容器中(参考)
先查目录文件大小:
(base) shl@zhihui-mint:~/shl_res/3_data/Aachen-Day-Night$ du --max-depth=1 -h aachen/
24K aachen/queries
2.2G aachen/3D-models
3.0G aachen/images
5.2G aachen/
(base) shl@zhihui-mint:~/shl_res/3_data/Aachen-Day-Night$ cd aachen/
拷贝命令:
docker ps 本地路径 [container ID] : 容器路径
docker cp /home/shl/shl_res/3_data/Aachen-Day-Night/aachen 0ec87e3e109a:/app/datasets
成功拷贝可以发现磁盘空间也变小了,此时的容器
可以在容器中查看到文件已经被从本地拷贝到容器中:
6、把本地的目录或文件映射到docker容器中(参考):
docker run -it --rm -p 8888:8888 -v 本地目录: docker容器中的目录 hloc:latest
使用:-v
参数进行映射,可以看到本地目录映射到容器目录之后,此时之前容器在该目录下的文件看不到了!
注意:
之所以看不到之前的容器
,是因为使用了--rm参数
,这个参数的意思,就是当运行一个容器的时候,如果容器已经存在,就删除创建一个新的容器!
9 docker常用命令总结
9.1 docker相关
1、查看docker版本信息
docker versino
或docker info
2、docker添加到用户组,不用使用docker时每次输入sudo
sudo usermod -aG docker $USER
3、启动docker
sudo service docker start
或sudo systemctl start docker
9.2 image镜像相关命令
1、查看本机有哪些镜像文件
docker images
或dockr image ls
2、删除镜像文件
docker image rm [imageName]
或docker image rm [imageName]:[tag]
或:
docker rmi ID
3、强制删除镜像
docker image rm -f [imageName]
或docker image rm -f [imageName]:[tag]
或:
docker rmi -f ID
9.3 container容器相关命令
1、列出所有正在运行
的容器
docker ps
或docker container ls
2、列出所有容器,包括终止运行的容器
docker container ls -a
或docker container ls --all
或:
docker ps -a
或docker ps --all
3、先远程仓库抓取镜像到本地
docker image pull library/[imageName]
或:
docker image pull [imageName]
4、运行容器
docker container run [imageName]
实例:
docker container run -p 8000:3000 -it koa-demo /bin/bash
5、停止运行容器
docker container kill [containerID]
或 在容器中输入:exit
或 直接在容器中按Ctrl+D
快捷键
使用这种方式,之前的容器就会被释放
,你在容器中安装的环境,传入的文件都没有了,当你再次启动一个容器的时候,就会从新从镜像中安装,因此最好把需要的环境一开始就写到Dockerfile
文件中,这样就可以把需要的环境都编译到image文件中!
退出容器之后,在容器中安装的额
6、删除容器
docker container rm [containerID]
7、重新运行终止的容器
docker container start [containerID]
8、进入一个正在运行容器的终端
docker container exec -it [containerID] /bin/bash
9、把容器中的文件或目录拷贝到本机
docker container cp [containID]:[/path/to/file] [local-path]
9.4 构建自己的image镜像
1、在.dockerignore
中,编写不打包到image中的文件路径
.git
node_modules
npm-debug.log
2、编写Dockerfile文件
:
FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
3、创建image文件
docker image build -t koa-demo .
# 或者
docker image build -t koa-demo:0.0.1 .
创建成功后查看自己创建的镜像:
docker images
4 、用自己创建的镜像生成容器
docker container run -p 8000:3000 -it koa-demo /bin/bash
# 或者
docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash