docker基础学习
核心概念
- 镜像
An image is a lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and config files.
做个类比,image很像kvm的虚拟机镜像qcow,里面包括软件APP、APP运行依赖的库、以及guest os等。 - 容器
A container is a runtime instance of an image—what the image becomes in memory when actually executed. It runs completely isolated from the host environment by default, only accessing host files and ports if configured to do so.
Containers run apps natively on the host machine’s kernel. They have better performance characteristics than virtual machines that only get virtual access to host resources through a hypervisor. Containers can get native access, each one running in a discrete process, taking no more memory than any other executable.
container概念理解起来比较简单,就是image运行起来的一个实例;和之前的kvm虚拟相比,更加轻量化(不包括OS,直接使用host的kernel以及物理资源等),也不存在敏感指令导致的陷入退出引发的系统开销,性能更佳;实际运行时,又通过namespace机制和host端运行环境完全隔离,安全机制高。 - swarm
A swarm is a group of machines that are running Docker and joined into a cluster. After that has happened, you continue to run the Docker commands you’re used to, but now they are executed on a cluster by a swarm manager. The machines in a swarm can be physical or virtual. After joining a swarm, they are referred to as nodes.
可以理解为以集群模式把多个物理机或虚拟机组织起来运行docker服务,但对docker client并无须感知过多,只用在manager节点上运行docker服务即可。 - 仓库
a repository is a collection of images.
自己开发的image可以放到仓库中去发布,销售,以及和别人共享;他人的成果我们也能直接拿来用,很像apple公司推出的app store的概念。
Docker Engine
docker engineengine以CS架构运行,包含以下组件:
- server:在后台运行的daemon进程(dockerd命令),可以用来创建和管理Docker的对象,包括images,containers,networks,volumes
- Rest Api:提供CLI和server交互的接口,通过这些Api来告知server去做什么
- CLI:client端(docker命令)
Docker 架构
[图片上传失败...(image-de869f-1510913691969)]
总结构CS模型,client和daemon可以运行在同一个host上,也可以连接client到远端的daemon上。
Registry
对应前面核心概念中的仓库,Registry用来存储images。当client执行docker pull或者docker run命令时,就会从配置好的Registry中去获取该命令依赖的image;对应的 docker push,会将本地的image放到Registry中。
Docker Objects
包括images,containers,services。这些对应的就是前面核心概念中介绍的,其中services类似swarm。
namespace
通过 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源 - cgroup。
安装
基于Ubuntu
$ sudo apt-get update
$ sudo apt-get install \
linux-image-extra-$(uname -r) \
linux-image-extra-virtual
1 uname -a
2 sudo apt-get update
3 sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
4 sudo apt-get update
6 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
8 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
9 sudo apt-get update
10 sudo apt-get install docker-ce
11 sudo docker run hello-world
使用
- 添加运行权限
运行docker命令时默认必须具有root权限,需要在运行docker命令前加sudo,或者采取如下步骤授予普通用户执行权限:
# 如果还没有docker group就添加一个:
$ sudo groupadd docker
# 将用户加入该group内。然后退出并重新登录即可生效。
$ sudo gpasswd -a ${USER} docker
# 重启docker
$ sudo service docker restart
- 保存对容器的更改:
sudo docker container commit 0ab1e61f8821 mycon
sudo docker ps
sudo docker container ls
sudo docker images
sudo docker image rm mycon
sudo docker images
- Search images
$ sudo docker search ubuntu
- Pull images
$ sudo docker pull ubuntu # 获取 ubuntu 官方镜像
$ sudo docker images # 查看当前镜像列表
- Running an interactive shell
$ sudo docker run -i -t ubuntu:14.04 /bin/bash
● docker run - 运行一个容器
● -t - 分配一个(伪)tty (link is external)
● -i - 交互模式 (so we can interact with it)
● ubuntu:14.04 - 使用 ubuntu 基础镜像 14.04
● /bin/bash - 运行命令 bash shell
注: ubuntu 会有多个版本,通过指定 tag 来启动特定的版本 [image]:[tag]
$ sudo docker ps # 查看当前运行的容器, ps -a 列出当前系统所有的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES6c9129e9df10 ubuntu:14.04 /bin/bash 6 minutes ago Up 6 minutes cranky_babbage
- 相关快捷键
● 退出:Ctrl-Dorexit
● detach:Ctrl-P + Ctrl-Q
● attach:docker attach CONTAINER-ID
- 列出容器
$ sudo docker ps # Lists only running containers
$ sudo docker ps -a # Lists all containers
$ sudo docker ps -l # List the last running container
- 控制容器
# 开始一个新的容器
$ JOB=$(sudo docker run -d ubuntu /bin/sh -c "while true; do echo Hello world; sleep 1; done")
# 停止容器
$ docker stop $JOB
# 开始容器
$ docker start $JOB
# 重启容器
$ docker restart $JOB
# 杀死一个工作
$ docker kill $JOB
# 删除一个容器
$ docker stop $JOB # Container must be stopped to remove it
$ docker rm $JOB
- 删除docker image
# 停止所有容器
$ docker stop $(docker ps -a -q)
# 删除指定镜像
$ docker rmi $image
# 删除无标示镜像,即id为<None>的镜像
$ docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
# 删除所有镜像
$ docker rmi $(docker images -q)
在docker中运行命令
docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。
构建APP
三个层次(自上而下):
- Stack
A stack is a group of interrelated services that share dependencies, and can be orchestrated and scaled together. A single stack is capable of defining and coordinating the functionality of an entire application (though very complex applications may want to use multiple stacks). - Service
Services are really just “containers in production.” A service only runs one image, but it codifies the way that image runs—what ports it should use, how many replicas of the container should run so the service has the capacity it needs, and so on. Scaling a service changes the number of container instances running that piece of software, assigning more computing resources to the service in the process. - Container
配置dockerfile,built image
将物理网卡映射到docker container中
The following low-level (i.e. not docker specific) network namespace tool commands can be used to transfer an interface from the host to a docker container:
CONTAINER=slave-play # Name of the docker container
HOST_DEV=ethHOST # Name of the ethernet device on the host
GUEST_DEV=test10gb # Target name for the same device in the container
ADDRESS_AND_NET=10.101.0.5/24
# Next three lines hooks up the docker container's network namespace
# such that the ip netns commands below will work
mkdir -p /var/run/netns
PID=$(docker inspect -f '{{.State.Pid}}' $CONTAINER)
ln -s /proc/$PID/ns/net /var/run/netns/$PID
# Move the ethernet device into the container. Leave out
# the 'name $GUEST_DEV' bit to use an automatically assigned name in
# the container
ip link set $HOST_DEV netns $PID name $GUEST_DEV
# Enter the container network namespace ('ip netns exec $PID...')
# and configure the network device in the container
ip netns exec $PID ip addr add $ADDRESS_AND_NET dev $GUEST_DEV
# and bring it up.
ip netns exec $PID ip link set $GUEST_DEV up
# Delete netns link to prevent stale namespaces when the docker
# container is stopped
rm /var/run/netns/$PID
更详细可以参考这里的链接。