ขอเริ่มต้นด้วย big promise คุณจะ absolutely LOVE บทความวันนี้ มันจะยาว 详细 และ highly useful 想想 GRUB, GRUB2 same thing here 只有我们要 tackle Docker 一个 nice distribution platform that wraps Linux Containers (LXC) technology in a simple convenient way
我将向您展示 how to get started 然后我们将 create our own containers with SSH and Apache 学习如何使用 Dockerfiles expose service ports 和解决大量的 little bugs and problems that normally never get addressed in public forums 请 without further ado 跟我来
Table of Contents
- Introduction
- Docker implementation
- Getting started
- Docker commands
- Pull image
- Start a Docker container
- Install Apache & SSH
- Start service
- Apache service
- SSH service
- Check if Web server is up
- Expose incoming ports
- Check IP address
- Testing new configuration
- Check if SSH works
- Wait what is the root password?
- Commit image
- Dockerfile
- Build image
- Test image
- Alternative build
- COPY instruction
- Advantages of containers
- Problems you may encounter & troubleshooting
- Additional commands
- Differences between exec and attach
- Differences between start and run
- Differences between build and create
- This is just a beginning ...
- More reading
- Conclusion
Introduction
我已经在 Gizmo's Freeware article 给出了 brief overview of the technology 有时去年 现在 我们将 get serious about using Docker 首先 重要的是要记住这个 framework allows you to use LXC in a convenient manner without having to worry about all the little details 它是这个世界的 next step 就像 OpenStack 是 virtualization world 的 next evolutionary step 让我给您一些 history and analogies
Virtualization 开始于 software that lets you abstractize your hardware 然后为了使事情更快 virtualization programs 开始使用 hardware acceleration 然后您也得到了 paravirtualization 最后 hypervisors 开始 popping up like mushrooms after rain 和它变得 somewhat difficult to provision and manage them all 这是核心原因 for concepts like OpenStack which hide different platforms under a unified API
Containers 开始他们的方式以类似的方式 首先 我们有 chroot 但 processes running inside the jailed environment shared the same namespace 和 fought for the same resources 然后 我们得到了 kexec system call which let us boot into the context of another kernel without going through the BIOS 然后 control groups came about allowing us to partition system resources like CPU, memory and others into subgroups thus allowing better control hence the name of processes running on the system
稍后 Linux kernel 开始 offering full isolation of resources using cgroups as the basic partitioning mechanism 技术上 这是 system-level virtualization technology allowing you to run multiple instances of the running kernel on top of the control host inside self-contained environments with the added bonus of very little performance penalty and overhead
Several competing technologies tried to offer similar solutions 像 OpenVZ 但 community 最终 narrowed down its focus to the native enablement inside the mainline kernel 和这似乎是未来的方向 仍然 LXC remains somewhat difficult to use 因为 a fair amount of technical knowledge and scripting is required to get the containers running
这是 Docker 发挥作用的地方 它试图 take away the gritty pieces 和 offer a simple method of spawning new container instances without worrying about the infrastructure backend Well almost 但 level of difficulty 少得多
Another strong advantage of Docker 是 widespread community acceptance 以及 emphasis on integration with cloud services 这里我们 full buzzword 这意味着 naming some of the big players like AWS, Hadoop, Azure, Jenkins 和其他人 然后我们也可以谈论 Platform as a Service (Paas) 和您可以想象这将在未来几年获得多少钱和关注 技术景观是 huge and confusing 和它 definitely going to keep on changing and evolving with more and more concepts and wrapper technologies coming into life and building on top of Docker
但我们要 focus on the technological side 一旦我们 master the basics 我们将 slowly expand 和 begin utilizing the strong integration capabilities the flexibility of the solution 和 work on making our cloud ecosystem expertise varied automated and just pure rad 那不会发生 right now 但我想帮助您 navigate the first few miles 或我们应该说 kilometers of the muddy startup waters 这样您就可以开始以 sensible efficient way 使用 Docker 由于这是一个年轻的技术 这是 Wild West out there 和大多数在线文档 tips tutorials 和 whatnot 都是 outdated copy & paste versions that do not help anyone 和 largely incomplete 我想今天 fix that
Docker implementation
有点更无聊的东西在我们做一些 cool things 之前 无论如何 Docker mostly about LXC 但不只是 它被设计为 extensible 和它也可以 interface with libvirt and systemd 以一种方式 这使它 almost like a hyper-hypervisor 因为有 potential for future growth 和当 additional modules are added 它 could effectively replace classic hypervisors like Xen or KVM or anything using libvirt and friends
This be a public domain image if you wondered.
Getting started
我们将 demonstrate using CentOS 7 不是 Ubuntu 大多数在线东西 focus on Ubuntu 但我想向您展示如何使用 as-near-as-enterprise flavor of Linux as possible 因为如果您将要使用 Docker 那将在某个 business-like 地方 第一件事是安装 docker:
yum install docker-io
一旦软件安装完毕 您可以开始使用它 然而 您可能会遇到以下两个问题 first time you attempt to run docker commands:
docker
FATA[0000] Get https:///var/run/docker.sock/v1.18/images/json: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?
和另一个错误是:
docker
FATA[0000] Get https:///var/run/docker.sock/v1.18/containers/json: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
原因是 您需要先 start the Docker service 此外 您必须 as root 运行这项技术 因为 Docker needs access to some rather sensitive pieces of the system 和 interact with the kernel 那就是它如何工作
systemctl start docker
现在我们可以 go crazy 和开始使用 Docker
Docker commands
基本的事情是运行 docker help 以获取 available list of commands 我不会 go through all the options 我们将 learn more about them as we go along 一般来说 如果您 ever in doubt 您应该 consult the pretty decent online documentation The complete CLI reference also kicks ass 然后还有 excellent cheat sheet on GitHub 但我们的第一个任务将是 download a new Docker image 和然后 run our first instance
Pull image
有许多 available images 我们想用 CentOS practice 这是一个 good starting point 一个 official repository is available 和它列出了所有 supported images and tags 确实 在此点 我们需要了解 Docker images 是如何 labeled 的
命名约定是 repository:tag 例如 centos:latest 换句话说 我们想要 latest CentOS image 但 required image 可能也是 centos:6.6 好的 让我们做吧
现在让我们 list the images by running the docker images command:
Start a Docker container
正如我们在 original tutorial 中看到的 simplest example 是运行 shell:
docker run -ti centos:centos7 /bin/bash
那么我们这里有什么? 我们正在运行一个新的 container instance 它有自己的 TTY (-t) 和 STDIN (-i) 从 CentOS 7 image 带有 BASH shell 几秒钟内 您将得到一个新的 shell 在 container 内部 现在 这是一个非常 basic 非常 stripped-down operating system 但您可以开始在里面 build things
Install Apache & SSH
让我们 setup a Web server 它也将有 SSH access 为此 我们将需要做一些 rather basic installations Grab Apache (httpd) 和 SSHD (openssh-server) 和配置它们 这与 Docker 本身无关 但这是一个 useful exercise
怎么 你们中的一些人可能会 clamor wait 你不需要 SSH 在 container 里面 它是 security risk 和 whatnot Well maybe yes and no depending on what you need and what you intend to use the container for 但让我们把 security considerations 放在一边 练习的目的是学习如何 setup and run ANY service
Start service
您可能想用 init script 或 systemd command start Apache 这将不太 work 具体来说 对于 CentOS 它带有 systemd 但更重要的是 container 没有自己的 systemd 如果您尝试 commands 将会失败
systemctl start httpd
Failed to get D-Bus connection: No connection to service manager.
有 hacks around this problem 和我们将在 future tutorial 中学习其中一些 但一般来说 鉴于 containers 的 lightweight and simple nature 您并不 really need a fully fledged startup service to run your processes 这确实增加了一些复杂性
Apache service
要运行 Apache (HTTPD) 只需执行 /usr/sbin/httpd 或您的 distro 中的 equivalent command 服务应该启动 很可能会有 warning that you have not configured your ServerName directive in httpd.conf 我们已经在 my rather extensive Apache guide 中学会了如何做到这一点
/usr/sbin/httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
SSH service
对于 SSHD 运行 /usr/sbin/sshd
/usr/sbin/sshd -f /etc/ssh/sshd_config
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_dsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
您也将失败 因为您不会有所有的 keys 通常 startup scripts take care of this 所以您将需要运行 ssh-keygen command 一次 before the service starts correctly 两个命令中的任何一个都可以工作:
/usr/bin/ssh-keygen -t rsa -f
/usr/bin/ssh-keygen -A
ssh-keygen: generating new host keys: RSA1 RSA DSA ECDSA ED25519
Check if Web server is up
现在 在 container 内部 我们可以看到 Apache 确实在运行
ps -ef|grep apache
apache 87 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 88 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 89 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 90 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 91 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
但如果我们想 check external connectivity? 在这一点上 我们手头有几个问题 第一 我们没有 setup any open ports 所谓的 第二 我们不知道我们的 container 的 IP address 是什么 现在 如果您尝试在 BASH shell 中运行 ifconfig 您不会到达任何地方 因为包含 basic networking commands 的必要包没有安装 好 因为它使我们的 container slim and secure
Expose incoming ports
像任何 Web server 一样 我们将需要 allow incoming connections 我们将使用 default port 80 这与 port forwarding 在您的 router 中没有区别 允许 firewall policies 和 whatnot 使用 Docker 有几种方式可以 achieve the desired result
当用 run command 启动一个新的 container 您可以使用 -p option 来指定要打开哪些端口 您可以选择单个端口或范围 并且您也可以 map both the host port (hostPort) 和 container port (containerPort) 例如:
- -p 80 将 expose container port 80 它将 automatically mapped to a random port on the host 我们稍后将学习如何 identify the correct port
- -p 80:80 将 map the container port to the host port 80 这意味着您不需要知道 container 的 internal IP address 有一个 internal NAT element involved which goes through the Docker virtual interface 我们将 soon discuss this 此外 如果您使用这种方法 只有一个 container 将能够 bind to port 80 如果您想使用 multiple Web servers with different IP addresses 您将必须设置它们每个都在不同的端口上
docker run -ti -p 22:22 -p 80:80 image-1:latest
FATA[0000] Error response from daemon: Cannot start container 64bd520e2d95a699156f5d40331d1aba972039c3c201a97268d61c6ed17e1619: Bind for 0.0.0.0:80 failed: port is already allocated
有许多 additional considerations IP forwarding, bridged networks, public and private networks, subnet ranges, firewall rules, load balancing 和更多 目前 我们不需要担心这些
还有一个 additional method of how we can expose port 但我们将在 later on discuss that 当我们 touch on the topic of Dockerfiles which are templates for building new images 现在 我们需要记住用 -p option 运行我们的 images
Check IP address
如果您想 leave your host ports free 那么您可以 omit the hostPort piece 在这种情况下 您可以 connect to the container directly 使用 its IP address 和 Web server port 要做到这一点 我们需要 figure out the container details:
docker inspect
这将给出一个 very long list of details 很像 KVM XML config 除了这个是用 JSON 写的 另一种 modern and ugly format for data 可读但 extremely ugly
docker inspect distracted_euclid
[{
"AppArmorProfile": "",
"Args": [],
"Config": {
"AttachStderr": true,
"AttachStdin": true,
"AttachStdout": true,
"Cmd": [
"/bin/bash"
],
"CpuShares": 0,
"Cpuset": "",
"Domainname": "",
"Entrypoint": null,
"Env": [
...
"ExposedPorts": {
"80/tcp": {}
},
"Hostname": "43b179c5aec7",
"Image": "centos:centos7",
"Labels": {},
"MacAddress": "",
...
我们可以 narrow it down to just the IP address
docker inspect
"IPAddress": "172.17.0.20",
Testing new configuration
让我们重新开始 Launch a new instance setup Apache start it 打开 Web browser 和 test 如果它 works 那么您已经 properly configured your Web server 正是我们想要的
docker run -it -p 80:80 centos:centos7 /bin/bash
如果我们检查正在运行的 container 我们可以看到 port mapping - output split over multiple lines for brevety 所以请 excuse that 通常 all-uppercase titles 将显示为 row header 然后您将 get all the rest printed below one container per line
# docker ps
CONTAINER ID IMAGE COMMAND
43b179c5aec7 centos:centos7 "/bin/bash"
CREATED STATUS PORTS
2 hours ago Up 2 hours 0.0.0.0:80->80/tcp
NAMES distracted_euclid
在浏览器中 我们得到:
Optional: 现在 internal IP address range 将只能在 host 上访问 如果您想让它从其他 machines accessible 您将需要您的 NAT and IP forwarding 和如果您想使用 names 那么您将需要 properly configure the /etc/hosts as well as DNS 对于 container 这可以使用 --add-host="host:IP" directive 当运行新 instance 时完成
另一个 note: 请记住 Docker 有自己的 internal networking 很像 VirtualBox 和 KVM 正如我们在 my other tutorials 中看到的 它是一个 fairly extensive /16 network 所以您有 quite a lot of freedom 在 host 上:
# /sbin/ifconfig
docker0: flags=4163
inet 172.17.42.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::5484:7aff:fe:fe:9799 prefixlen 64 scopeid 0x20
ether 56:84:7a:fe:97:99 txqueuelen 0 (Ethernet)
RX packets 6199 bytes 333408 (325.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11037 bytes 32736299 (31.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Check if SSH works
我们需要做 same exercise with SSH 同样这意味着 expose port 22 和我们有 several options available 为了使它更有趣 让我们尝试 random port assignment:
docker run -ti -p 20 -p 80 centos:centos7 /bin/bash
如果我们用 docker ps 检查 specifically for ports:
0.0.0.0:49176->22/tcp, 0.0.0.0:49177->80/tcp boring_mcclintock
这意味着您可以 connect to the docker0 IP address ports as specified above in the docker ps command output 和这 equivalent to actually connecting to the container IP directly on their service port 这可以有用 因为您不需要担心 internal IP address that your container uses 和它可以简化 forwarding 现在 让我们尝试连接 我们可以使用 host port 或我们可以使用 container IP directly
ssh 172.17.42.1 -p 49117
Either way 我们将得到我们需要的 例如:
ssh 172.17.0.5
The authenticity of host '172.17.0.5 (172.17.0.5)' can't be established. ECDSA key fingerprint is 00:4b:de:91:60:e5:22:cc:f7:89:01:19:3e:61:cb:ea.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts.
root@172.17.0.5's password:
Wait what is the root password?
我们将失败 因为我们没有 root password 那么我们现在做什么? 同样 我们有 several options 首先 尝试 change the root password inside the container using the passwd command 但这不会 work 因为 passwd utility not installed 我们可以然后 grab the necessary RPM and set it up inside the container 在 host 上 检查 dependencies:
rpm -q --whatprovides /etc/passwd
setup-2.8.71-5.el7.noarch
但这是一个 security vulnerability 我们想要我们的 containers to be lean 所以我们可以 just copy the password hash from /etc/shadow on the host into the container 稍后 我们将学习 about a more streamlined way of doing it
另一件很清楚的事情是 我们在重复所有的 actions 这不是 efficient 这也是为什么我们想要 preserve changes we have done to our container 下一节处理那个
Commit image
在您对 container 做出更改后 您可能想要 commit it 换句话说 当稍后启动一个新的 container 时 您将不需要从头开始重复所有步骤 您将能够 reuse your existing work 和 save time and bandwidth 您可以根据其 ID 或其 alias commit an image:
docker commit
例如 我们得到以下:
docker commit 43b179c5aec7 myapache3
1ee373ea750434354faeb1cb70b0177b463c51c96c9816dcdf5562b4730dac54
再次检查 images 列表:
Dockerfile
A more streamlined way of creating your images 是使用 Dockerfiles 以一种方式 它就像使用 Makefile for compilation 只是在 Docker format 中 或如果您愿意 RPM specfile 基本上 在任何一个 "build" directory 中 创建一个 Dockerfile 我们将学习我们可以在其中放什么东西 和为什么我们想要它 for our Apache + SSH exercise 然后 我们将从它 build a new image 我们可以将它与我们的 committed images 结合以 preserve changes already done inside the container like the installation of software 以使它更快并节省网络利用率
在我们进一步之前 让我们看看一个我们将用于我们练习的 Dockerfile 此刻 commands 可能不 make much sense 但它们很快就会
FROM myhttptest2:latest
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
EXPOSE 80
RUN mkdir -p /run/httpd
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
我们这里有什么?
- The FROM directory tells us what repo:tag to use as the baseline 在我们的例子中 它是 one of the committed images that already contains the httpd and sshd binaries SSH keys 和 a bit more
- EXPOSE 22 - 这一行 expose port 22 inside the container 我们可以进一步 map it using the -p option at runtime 同样的道理适用于 EXPOSE 80 which is relevant for the Web server
- CMD ["/usr/sbin/sshd", "-D"] - 这个 instruction runs an executable with optional arguments 它就是这么简单
- RUN mkdir -p /run/httpd - 这个 instruction runs a command in a new layer on top of the base image - 和 COMMITS the results 这非常重要 to remember 因为我们将 soon discuss what happens if you don't use the RUN mkdir thingie with Apache
- CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"] - 我们运行 server 在 foreground 最后一点是 optional 但 for the time being 您可以用这种方式 start Apache Good enough
正如您所见 Dockerfiles 不是那么 complex or difficult to write 但它们 highly useful 您可以 pretty much add anything you want 使用这些 templates 形成 automation 的基础 和有了 conditional logic 您可以 create all sorts of scenarios 和 spawn containers that match your requirements
Build image
一旦您有 Dockerfile in place 该是时候 build a new image 了 Dockerfiles must follow a strict convention 就像 Makefiles 最好 keep different image builds in separate sub-directories 例如:
docker build -t test5 .
Sending build context to Docker daemon 41.47 kB
Sending build context to Docker daemon
Step 0 : FROM myapache4:latest
---> 7505c70235e6
Step 1 : EXPOSE 22 80
---> Using cache
---> 58f11217c3e3
Step 2 : CMD /usr/sbin/sshd -D
---> Using cache
---> 628c3d6b5399
Step 3 : RUN mkdir -p /run/httpd
---> Using cache
---> 5fc118f61a4d
Step 4 : CMD /usr/sbin/httpd -D FOREGROUND
---> Using cache
---> d892acd86198
Successfully built d892acd86198
该命令告诉我们以下内容: -t repository name from a Dockerfile stored in the current directory (.) 那就是全部 非常简单和优雅
Test image
从创建的 image 运行一个新的 container 如果一切顺利 您应该有 both SSH connectivity 和 a running Web server in place 再次 所有 usual network related rules apply
Alternative build
一旦您有了知识 how do it on your own 您可以尝试 one of the official Apache builds 确实 Docker repository 包含很多好东西 所以您应该 definitely invest time checking available templates 对于 Apache 您只需要以下在您的 Dockerfile 中 - 第二行是 optional
FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/
COPY instruction
我们上面有什么? 基本上 在 Dockerfile 中 我们有 declaration what template to use 然后 我们有 COPY instructions which will look for a public-html directory in the current folder and copy it into the container during the build 以同样的方式 您也可以 copy your httpd.conf file 取决于您的 distribution paths and filenames might differ 最后 在建立 image 和运行 container 后:
docker run -ti -p 22 -p 80 image-1:latest
AH00558: httpd: Could not reliably determine the server's fully qualified domain name using 172.17.0.17. Set the 'ServerName' directive globally to suppress this message
[Thu Apr 16 21:08:35.967670 2015] [mpm_event:notice] [pid 1:tid 140302870259584] AH00489: Apache/2.4.12 (Unix) configured -- resuming normal operations
[Thu Apr 16 21:08:35.976879 2015] [core:notice] [pid 1:tid 140302870259584] AH00094: Command line: 'httpd -D FOREGROUND'
Advantages of containers
有许多 good reasons 为什么您想要使用这项技术 但让我们 just briefly focus on what we gain by running these tiny isolated instances 当然 有很多事情发生在 hood 下 在 kernel 中 但一般来说 spawned containers 的 memory footprint 是 fairly small 在我们的例子中 SSH + Apache containers 使用 a tiny fraction of extra memory Compare this to any virtualization technology
Problems you may encounter & troubleshooting
让我们回到 Apache example 现在您也将学习为什么这么多在线教程 sin the sin of copy & pasting information without checking 和为什么大多数 advice is not correct unfortunately 它与 what do you do if your Apache server seems to die within a second or two after launching the container 有关 确实 如果这发生 您想要 step into the container and troubleshoot 为此 您可以使用 docker exec command to attach a shell to the instance
docker exec -ti boring_mcclintock /bin/bash
然后 它归结为 reading logs 和 trying to figure out what might have gone wrong 如果您的 httpd.conf configured correctly 您将有 access and error logs under /var/log/httpd:
[auth_digest:error] [pid 25] (2)No such file or directory: AH01762: Failed to create shared memory segment on file /run/httpd/authdigest_shm.25
A typical problem 是您可能 missing /run/httpd directory 如果这个不存在在您的 container 中 httpd 将 start and die 听起来这么简单 但 few if any reference mentions this
当 initially playing with containers 我确实遇到这个问题 Reading online 我找到了 several suggestions none of which really helped 但我确实想 elaborate on them 和 how you can make progress in your problem solving 即使 intermediate steps aren't really useful
Suggestion 1: You must use -D FOREGROUND to run Apache 和您也必须使用 ENTRYPOINT rather than CMD 两个 instructions 之间的 difference 非常 subtle 并且它 does not solve our problem in any way
ENTRYPOINT ["/usr/sbin/httpd"]
CMD ["-D", "FOREGROUND"]
Suggestion 2: Use a separate startup script which could work around any issues with the starting or restarting of the httpd service 换句话说 Dockerfile 变成像这样:
...
EXPOSE 80
COPY ./run-httpd.sh /run-httpd.sh
RUN chmod -v +x /run-httpd.sh
CMD ["/run-httpd.sh"]
而 run-httpd.sh script 的内容在以下 lines 上:
#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND
Almost there 移除任何 old leftover PID files 但这些通常不存储在 /run/httpd 下 相反 您将在 /var/run/httpd 下找到它们 此外 我们不确定这个目录是否存在
最后 这个想法是 work around any problems with the execution of a separation shell inside which the httpd thread is spawned 虽然它确实提供了 additional useful lessons on how to manage the container with COPY and RUN instructions 它不是我们需要 fix the issue 的东西
Step 3 : EXPOSE 80
---> Using cache
---> 108785c8e507
Step 4 : COPY ./run-httpd.sh /run-httpd.sh
---> 582d795d59d4
Removing intermediate container 7ff5b58b40bf
Step 5 : RUN chmod -v +x /run-httpd.sh
---> Running in 56fadf4dd2d4
mode of '/run-httpd.sh' changed from 0644 (rw-r--r--) to 0755 (rwxr-xr-x)
---> 928640f680cf
Removing intermediate container 56fadf4dd2d4
Step 6 : CMD /run-httpd.sh
---> Running in f9c6b30795e2
---> b2dcc2818a27
Removing intermediate container f9c6b30795e2
Successfully built b2dcc2818a27
这不会工作 因为 apachectl is an unsupported command for managing httpd 而且我们已经看到 problems using startup scripts and utilities earlier 和我们将在 separate tutorial 中修复这个
docker run -ti -p 80 image-2:latest
Passing arguments to httpd using apachectl is no longer supported You can only start/stop/restart httpd using this script If you want to pass extra arguments to httpd edit the /etc/sysconfig/httpd config file
但它有用 to try these different things to get the hang of it 不幸的是 它也 highlights the lack of maturity and the somewhat inadequate documentation for this technology out there
Additional commands
有许多方式您可以 interact with your container 如果您不想 attach a new shell to a running instance 您可以使用 a subset of docker commands directly against the container ID or name:
docker
例如 要从 container 获取 top output:
docker top boring_stallman
如果您有 too many images 一些只是用于 testing 那么您可以 remove them to free up some of your disk space 这可以用 docker rmi command 做到
# docker rmi -f test7
Untagged: test7:latest
Deleted: d0505b88466a97b73d083434b2dd0e7b59b9a5e8d0438b1bf8c6c
Deleted: 5fc118f61bf856f6f3d90e0e71076b737fa7cc58cd56785ea7904
Deleted: 628c3d6b53992521c9c1fdda4148693347c3d10b1d130f7e091e7
Deleted: 58f11217c3e31206b4e41d07100a797cd4d17e4569b0fdb8b7a18
Deleted: 7505c70235e638c54028ea5b63eba2b691de6bee67c2cb5e2861a
...
然后 您也可以在后台运行您的 containers 使用 -d flag 将 exactly do that 和您将 get the shell prompt back 这也有用如果您不 mask signals 所以如果您 accidentally break in your shell 您可能会 kill the container when it's running in the foreground
docker run -d -ti -p 80 image-3:latest
您也可以 check events examine changes inside a container's filesystem as well as check history 所以您 basically have a version control in place export or import tarred images to and from remote locations 包括 over the Web 和更多
Differences between exec and attach
如果您读过 documentation 您会注意到您可以 connect to a running container using either exec or attach commands 那么什么是 difference 您可能会问? 如果我们看 official documentation 那么:
docker exec command runs a new command in a running container 使用 docker exec 启动的命令仅在 container's primary process (PID 1) running 时运行 并且如果 container 被重启 它不会被重启
另一方面 attach 给您以下内容:
docker attach command allows you to attach to a running container using the container's ID or name either to view its ongoing output or to control it interactively 您可以同时多次 attach to the same contained process screen sharing style 或 quickly view the progress of your daemonized process 您可以 detach from the container (and leave it running) with CTRL-p CTRL-q (for a quiet exit) or CTRL-c which will send a SIGKILL to the container 当您 attached to a container 并且 exit its main process 该 process's exit code will be returned to the client
换句话说 使用 attach 您将得到一个 shell 和能够做任何您需要的 使用 exec 您可以发出不需要任何交互的命令 但如果您使用 shell 结合 exec 您将 achieve the same result 就好像您使用了 attach
Differences between start and run
Start is used to resume the execution of a stopped container 它 not used to start a fresh instance 对于那个 您有 run command 词语的选择 could have been better
Differences between build and create
第一个命令用于从 Dockerfile 创建新 image 另一方面 后者用于使用 command line options and arguments 创建新 container Create lets you specify container settings too 像 network configurations resource limitations 和 other settings which affect the container from the outside 而由 build command 实现的 changes will be reflected inside it 一旦您 start an instance 和 by start 我指的是 run Get it?
This is just a beginning ...
有一百万更多的事情我们可以做: 使用 systemd enabled containers policies security resource constraints proxying signals other networking and storage options 包括 the super-critical question of how to mount data volumes inside containers so that data does not get destroyed when containers die additional pure LXC commands 和更多 我们 barely scratched the surface 但现在 我们知道 what to do 和我们将到达那里 Slowly but surely
More reading
我建议您 allocate a few hours 然后 spend some honest time reading all of the below in detail 然后 practice 这是唯一的方式您将 really fully understand and embrace the concepts
- My entire virtualization section
- Dockerizing an SSH Deamon Service
- Differences between save and export in Docker
- Docker Explained: Using Dockerfiles to Automate Building of Images
Conclusion
我们今天完成了这个 tutorial 希望您发现它 useful 简而言之 它确实解释了相当多的事情 包括如何开始使用 Docker 如何 pull new images 运行 basic containers 添加 services like SSH and Apache commit changes to a file expose incoming ports build new images with Dockerfiles lots of troubleshooting of problems additional commands 和更多 Eventful and colorful 我敢说
在未来 我们将 significantly expand on what we learned here 和 focus on various helper technologies like supervisord for instance 我们将学习如何 mount filesystems work on administration and orchestration 和 many other cool things Docker 是一个 very nice concept 和如果正确使用 它可以使您的 virtual world easier and more elegant 最初的几步是 rough 但 with some luck 这个 guide 将提供了 right dose of karma to get happily and confidently underway Ping me if you have any requests or desires Technology related of course 我们完成了
P.S. 如果您喜欢这篇文章 那么您最好给一些爱回给 Dedoimedo!
Cheers.