什 么 是 容 器?
容器只是实现隔离的一种方法。与虚拟机不同,它们不是通过模拟硬件来实现隔离,而是通过使用现有的Linux内核功能来实现隔离。在典型的Unix/Linux操作系统中,所有进程都共享相同的用户空间,但是随着Linux 2.6+中新功能的引入,您可以创建一个进程,该进程具有自己特定的一组隔离上下文的进程,如文件树、线程等。这些功能与其他内核技术结合在一起是容器的神奇之处!
◆ ◆ ◆ ◆ ◆
在本文中,我将介绍基本的Docker命令和概念。读完后,您将能够采用一些Docker功能来加速和简化您的日常工作流程。
安装Docker
在OS X/Windows中,使用安装向导安装Docker是一项简单的任务。您可以在Docker社区页面上找到操作系统的安装程序。在Linux上,Docker通常在分发包管理器中可用。
在Fedora中安装Docker :
sudo dnf install docker
要开始这个过程:
sudo systemctl start docker
要使Docker进程启动和启动时间:
sudo systemctl enable docker
在使用Systemd的其他Linux发行版中,这些步骤应该类似。
入门
Hello World
完成安装后,我们应该尝试一个Hello World!
#sudo is only for Linuxsudo docker run --name hello -it busybox echo "Hello World!" # Hello World!
只有在运行某些Linux发行版时才需要使用sudo,但请记住,Docker需要管理员权限创建容器。在OSX和Windows编写本文时,本文使用了一些基于Linux的虚拟机,因此Docker命令可以在这些系统中没有特权用户的情况下运行。
如何运行
sudo docker run
run选项创建并运行一个容器,其中一个属性是docker将容器的生命绑定到正在运行的进程(在本例中是linux命令echo),这意味着当进程完成时,容器将终止。
- name:我们设置容器的名称,如果您不选择任何内容,Docker将随机选择一个。
- it:这意味着交互,它将我们的终端连接到容器虚拟tty的输出,允许与正在运行的进程交互。
- busybox:这是创建容器的基本映像,将其视为zip文件,其中包含运行所需应用程序所需的文件和文件夹。在Docker Hub中有一个完整的社区基础图像,我使用BusyBox,因为它非常轻,只有715 kb的压缩空间。
- echo:正如我们前面提到的,echo是我们试图执行的命令,它包含在busybox映像中。
如果要检查busybox中可用的命令,请执行以下操作:
sudo docker run -it busybox ls /bin/
列出镜像
当您第一次执行docker命令时,您可以使用以下命令检查本地镜像:
sudo docker images
在守护进程模式下运行
在某些情况下,我们不希望直接与某些应用程序(如服务器)交互,在这种情况下,我们希望生成进程并返回我们的终端继续执行一些工作,Docker为我们提供了一种在守护进程模式下执行进程的方法像这样的-d参数:
sudo docker run - d - name snooze busybox sleep 15
此过程将在后台运行15秒,然后退出。
列出后台运行容器
容器在后台运行后,您可以使用ps检查其状态:
sudo docker ps
杀死运行容器
停止容器很简单:
sudo docker stop [name of your container]#examplesudo docker stop snooze
此命令将停止正在运行的容器,但Docker服务将保留您创建的容器,包括其关联的命令缓存在磁盘中。如果需要重新启动,只需执行:
sudo docker start snooze
如果想要更改配置并重新使用容器名称,则需要停止并删除容器,假设我们要更改休眠容器,使其休眠10秒而不是15秒:
# stop & cleansudo docker stop snoozesudo docker rm snooze# re-createsudo docker run -d --name snooze busybox sleep 10
安装
-v参数将使我们能够挂载/从一个文件夹映射主机(我们的电脑)到容器内的文件夹中。
我们来创建一个文件:
echo 'Hello World' > hello
现在我们要使用busybox中提供的隔离文本编辑器打开文件:
# Opening the file with our contained VIMsudo docker run -it busybox vi hello
没有任何反应,这是因为我们调用的vi进程是隔离的,无法访问包含区域之外的文件。要解决这个问题,我们需要挂载文件夹,以便我们的编辑器能够找到该文件。
#the :z in /app:z -> is for SELinux, non-Linux can ignore this.sudo docker run -it -v "$(pwd)":/app:z busybox vi app/text
这会将实际文件夹$(pwd)装入容器中的文件夹/应用程序。如果文件夹中不存在,那么将创建它,然后使用vi并传递挂载文件夹vi app/hello的文件位置。
一些观察结果:
- 该v将覆盖容器中以前的任何文件夹。如果存在,它将替换为提供的文件夹。
- 这个命令实际上是挂载文件夹,所以一旦容器被杀死,容器对这个文件夹所做的每一个更改都将被持久化,如果您希望数据库在容器生命周期之外持久化其数据,这是一个好主意。
- 容器将可以访问您的系统资源(共享文件夹),因此请小心。
联网
-p允许我们公开一个隔离端口并将其传递给特定的主机端口。
为了说明网络如何与容器一起工作,首先让我们开始编写一个简单的Javascript脚本来启动服务器。我们将在本地机器上执行此操作,所以让我们编写一些代码。
require('http') .createServer((req, res) => { res.end('Hello World!') }).listen(8080)
我们将调用这个文件index.js,它基本上创建了一个在端口8080中等待连接的服务器。当有人连接时,它会发送一个Hello World!
下一步是在容器中运行脚本。我们可以通过编写以下命令来完成此操作:
sudo docker run - it - v “$(pwd)”:/ app:z - name myserver mhart / alpine - node node app / index。JS
这里的新东西是mhart / alpine-node的基本镜像,它将拉出一个Node.JS容器,然后将像我们之前那样使用-v挂载文件夹,然后执行隔离节点app / index.js进程。
让我们看看我们的服务器是否正常工作:
sudo docker exec -it myserver wget -qO- localhost:8080# Hello World%
这个命令测试我们的服务器在容器中工作,我们应该返回hello world%。现在,让我们尝试从主机连接,打开一个新终端,然后写:Hello World%
curl http://localhost:8080#curl: (7) Failed to connect to localhost port 8080: Connection refused
我们无法连接,因为容器网络是孤立的; 我们需要拉取之前的端口:
# stopping our containersudo docker stop myserver sudo docker rm myserversudo docker run -it -v "$(pwd)":/app:z -p 8080:8080 --name myserver mhart/alpine-node node app/index.js
现在尝试在浏览器中打开http:// locahost:8080,你应该看到一个 hello world!
恭喜!你已经编写了一个很好的NodeJS应用程序。最大的优势之一是您可以在不安装NodeJS的情况下执行此操作,并且可以使用此功能来安装其他类型的软件,如数据库,其他微服务等。
一些快速提示
在我的日常工作中,我总是需要与MongoDB和Redis集成,但是安装它们通常是一个痛苦的过程,我通过在.zshrc中创建一些bash脚本来解决这个问题。
function new_mongo { docker run -d --name mongodb -p 27017:27017 mongo}# the : here means image tag, usually if the image is done correctly # like in this case tag version match the Redis versionfunction new_redis { docker run -d --name redis -p 6379:6379 redis:3.2}function stop_mongo { docker stop mongodb docker rm mongodb}function stop_redis { docker stop redis docker rm redis}
new_mongo # it will spin up a new mongodb instance. new_redis # it will spin up a new redis instance. # to stop this containers stop_mongostop_redis
现在,您将能够按需配置部署本地MongoDB或Redis实例,并且一个优点(至少在我看来)是这些实例中的数据是短暂的,这意味着当您终止容器时它将重置数据库也是如此,释放占用的空间。
linux安全性
如果您在Fedora中使用-v参数执行挂载文件夹,可能会收到此错误:
sudo docker run -it -v "$(pwd)":/app busybox ls app/text#ls: can't open '.': Permission denied
这是因为SELinux默认策略将保护主机中的任何读/写,以防攻击者离开容器,SELinux将通过在内核级强制执行安全规则来阻止您。
要在SELinux感知机器中安装文件夹,您需要传递z参数,这将更改SELinux上下文并允许容器执行安装。
# "$(pwd)" will get the actual directory, is equivalent to do pwddocker run -it -v "$(pwd)":/app:z busybox /bin/sh
另一种方法(但不建议这样做)是暂时禁用此保护:
su -c "setenforce 0"
完成后,您可以通过以下操作启用它:
su - c “setenforce 1”