Computer >> Hướng Dẫn Máy Tính >  >> Phần Mềm >> Máy Ảo

Hướng Dẫn Toàn Diễn Docker Containers Cho Người Mới: Setup, Sử Dụng & Best Practices

Bắt đầu với lời hứa lớn. Bạn sẽ ABSOLUTELY LOVE bài này. Dài, chi tiết, highly useful. Nghĩ GRUB, GRUB2. Cùng idea. Tackle Docker: distribution platform wrap Linux Containers (LXC) technology simple, convenient.

Show getting started, tạo containers SSH + Apache, dùng Dockerfiles, expose service ports, solve immense số little bugs/problemsnormally never addressed public forums. Without further ado, follow me.

Table of Contents

  1. Introduction
  2. Docker implementation
  3. Getting started
  4. Docker commands
  5. Pull image
  6. Start a Docker container
  7. Install Apache & SSH
    1. Start service
    2. Apache service
    3. SSH service
  8. Check if Web server is up
    1. Expose incoming ports
    2. Check IP address
    3. Testing new configuration
  9. Check if SSH works
    1. Wait, what is the root password?
  10. Commit image
  11. Dockerfile
    1. Build image
    2. Test image
  12. Alternative build
    1. COPY instruction
  13. Advantages of containers
  14. Problems you may encounter & troubleshooting
  15. Additional commands
    1. Differences between exec and attach
    2. Differences between start and run
    3. Differences between build and create
  16. This is just a beginning ...
  17. More reading
  18. Conclusion

Introduction

Brief overview tech trong Gizmo's Freeware article năm ngoái. Bây giờ serious về Docker. Quan trọng: framework cho phép dùng LXC convenient, không lo infrastructure backend. Next step container world, giống OpenStack next evolutionary step virtualization world. History và analogies.

Virtualization bắt đầu software abstractize hardware. Pot speedier: hardware acceleration, paravirtualization. Cuối cùng hypervisors mọc như nấm sau mưa, provision/manage khó. Core reason concepts như OpenStack: hide different platforms unified API.

Containers similar journey. Chroot: processes jailed environment shared namespace, fight same resources. Kexec system call: boot context another kernel without BIOS. Control groups (cgroups): partition system resources (CPU, memory...) subgroups, better control processes.

Sau: Linux kernel full isolation resources, cgroups basic partitioning mechanism. System-level virtualization technology: run multiple instances running kernel trên control host trong self-contained environments, bonus: very little performance penalty/overhead.

Competing technologies: OpenVZ, nhưng community narrow focus native enablement mainline kernel -> future direction. Vẫn LXC difficult use: technical knowledge/scripting required get containers running.

Docker comes in. Take away gritty pieces, simple method spawn container instances without worry infrastructure backend. Well, almost. Difficulty level much less.

Strong advantage Docker: widespread community acceptance, emphasis integration cloud services. Buzzword: AWS, Hadoop, Azure, Jenkins... Platform as a Service (PaaS). Money/focus coming years. Landscape huge/confusing, keep changing/evolving, more concepts/wrapper technologies building on Docker.

Focus technological side. Master basics -> slowly expand strong integration capabilities, flexibility, make cloud ecosystem expertise varied, automated, pure rad. Not now, but help navigate first few miles/kilometers muddy startup waters, begin using Docker sensible/efficient. Young technology -> Wild West, online docs/tips/tutorials outdated, copy-paste, incomplete. Fix today.

Docker Implementation

Boring stuff trước cool things. Docker mostly LXC nhưng not just. Designed extensible, interface libvirt và systemd. Way: almost hyper-hypervisor, potential future growth, additional modules added -> effectively replace classic hypervisors (Xen, KVM, anything libvirt).

Hướng Dẫn Toàn Diễn Docker Containers Cho Người Mới: Setup, Sử Dụng & Best Practices

Public domain image.

Getting Started

Demo CentOS 7. Không Ubuntu. Online stuff focus Ubuntu, nhưng show enterprise flavor Linux, vì Docker -> business-like. First: install docker:

yum install docker-io

Installed -> start using. But may encounter 2 issues first 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?

Other error:

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?

Reason: cần start Docker service first. Must run as root (Docker cần access sensitive system pieces, interact kernel). That's how it works.

systemctl start docker

Now go crazy use Docker.

Docker Commands

Basic: docker help -> available commands. Không go through all. Learn as we go. Doubt -> online documentation. Complete CLI reference kicks ass. Excellent cheat sheet GitHub. First mission: download new Docker image, run first instance.

Pull Image

Many available images. Practice CentOS. Good starting point. Official repository lists supported images/tags. Understand Docker image labeling.

Naming convention: repository:tag, VD centos:latest. Want latest CentOS image. Required image có thể centos:6.6. Let's do it.

List images: docker images command.

Start a Docker Container

Simplest example: run shell:

docker run -ti centos:centos7 /bin/bash

Run new container instance own TTY (-t) và STDIN (-i), từ CentOS 7 image, BASH shell. Giây lát -> new shell inside container. Basic, stripped-down OS, nhưng build things inside.

Install Apache & SSH

Setup Web server + SSH access. Cần basic installations. Grab Apache (httpd) và SSHD (openssh-server), configure. Nothing to do with Docker per se, nhưng useful exercise.

Some may clamor: không cần SSH trong container, security risk. Maybe yes/no, depending needs/intended use. Leave security considerations aside. Purpose: learn setup/run ANY service.

Start Service

Start Apache init script/systemd command. Not quite work. CentOS có systemd, nhưng container không có own systemd. Try -> commands fail.

systemctl start httpd
Failed to get D-Bus connection: No connection to service manager.

Hacks around this, future tutorial. But general: lightweight/simple nature containers -> không cần fully fledged startup service run processes. Adds complexity.

Apache Service

Run Apache (HTTPD): execute /usr/sbin/httpd (hoặc equivalent distro). Service start, likely warning ServerName directive httpd.conf. Learned 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: run /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

Fail: không có keys. Startup scripts normally take care -> run ssh-keygen once trước service start correctly. Either command works:

/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

Inside container, Apache running.

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

External connectivity? 2 problems: 1) chưa setup open ports. 2) không biết container IP. ifconfig trong BASH shell -> nowhere, package networking commands not installed. Good: container slim/secure.

Expose Incoming Ports

Web server: allow incoming connections. Default port 80. Giống port forwarding router, firewall policies. Docker: several ways achieve result.

Start new container run command: -p option specify ports open. Single port hoặc range, map hostPort và containerPort. VD:

  • -p 80: expose container port 80, auto map random host port. Sẽ learn identify correct port.
  • -p 80:80: map container port -> host port 80. Không cần internal IP container. Internal NAT involved qua Docker virtual interface. Discuss soon. Chỉ 1 container bind port 80. Multiple web servers different IPs -> setup different ports.

docker run -ti -p 22:22 -p 80:80 image-1:latest
FATA[0000] Error response from daemon: Cannot start container ... Bind for 0.0.0.0:80 failed: port is already allocated

Additional considerations: IP forwarding, bridged networks, public/private networks, subnet ranges, firewall rules, load balancing. Not worry now.

Additional method expose port: discuss later Dockerfiles (templates build new images). Remember run images với -p option.

Check IP Address

Muốn free host ports -> omit hostPort. Connect container directly: IP address + Web server port. Need container details:

docker inspect

Long list details, giống KVM XML config nhưng JSON (modern ugly format). Readable but 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 down IP address:

docker inspect | grep -i "ipaddr"
"IPAddress": "172.17.0.20",

Testing New Configuration

Start fresh. Launch new instance, setup Apache, start. Open browser test. Works -> properly configured Web server. Exactly what we wanted.

docker run -it -p 80:80 centos:centos7 /bin/bash

Check running container port mapping (output split lines brevity). Normally uppercase titles row header, 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

Browser:

Optional: internal IP range chỉ accessible on host. Accessible other machines -> NAT/IP forwarding. Names -> configure /etc/hosts + DNS. Container: --add-host="host:IP" directive run new instance.

Note: Docker internal networking giống VirtualBox/KVM (seen other tutorials). Extensive /16 network, quite a lot freedom. Host:

# /sbin/ifconfig
docker0: flags=4163 mtu 1500
inet 172.17.42.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::5484:7aff:fefe: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 SSH. Expose port 22, several options. More interesting: random port assignment:

docker run -ti -p 20 -p 80 centos:centos7 /bin/bash

Check docker ps ports:

0.0.0.0:49176->22/tcp, 0.0.0.0:49177->80/tcp boring_mcclintock

Connect docker0 IP address, ports docker ps output, equivalent connect container IP directly service port. Useful: không lo internal IP container, simplify forwarding. Try connect. Host port hoặc container IP directly.

ssh 172.17.42.1 -p 49117

Either way get need, VD:

ssh 172.17.0.5
The authenticity of host '172.17.0.5 (172.17.0.5)' can't be established. ECDSA key fingerprint 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 known hosts.
root@172.17.0.5's password:

Wait, What Is The Root Password?

Fail: no root password. Options: change root password inside container passwd command. Won't work: passwd utility not installed. Grab necessary RPM setup inside container. Host check dependencies:

rpm -q --whatprovides /etc/passwd
setup-2.8.71-5.el7.noarch

Security vulnerability. Want containers lean. Copy password hash từ /etc/shadow host vào container. Later: streamlined way.

Striking: repeating all actions. Not efficient -> preserve changes container. Next section handles that.

Commit Image

Sau changes container, may want commit. Nghĩa: start new container later -> không repeat steps from scratch, reuse existing work, save time/bandwidth. Commit image based on ID hoặc alias:

docker commit

Example:

docker commit 43b179c5aec7 myapache3
1ee373ea750434354faeb1cb70b0177b463c51c96c9816dcdf5562b4730dac54

Check images list again.

Dockerfile

Streamlined way create images: Dockerfiles. Giống Makefile compilation, chỉ Docker format. Hoặc RPM specfile. Basically, any "build" directory, create Dockerfile. Learn what put inside, why for Apache+SSH exercise. Build new image from it. Combine committed images preserve changes done inside container (software installation) -> faster, save network.

Before further, look Dockerfile for exercise. Commands may not make sense now, but soon will.

FROM myhttptest2:latest
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
EXPOSE 80
RUN mkdir -p /run/httpd
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

What we have:

  • FROM: baseline repo:tag. Case: committed image đã chứa httpd/sshd binaries, SSH keys, more.
  • EXPOSE 22: expose port 22 inside container. Map further -p option runtime. Same EXPOSE 80 cho Web server.
  • CMD ["/usr/sbin/sshd", "-D"]: run executable với optional arguments.
  • RUN mkdir -p /run/httpd: run command new layer on top base image - COMMITS results. Important: discuss what happens nếu không RUN mkdir với Apache.
  • CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]: run server foreground. Last bit optional, but time being start Apache this way. Good enough.

Dockerfiles không complex/difficult, nhưng highly useful. Add anything. Templates form basis automation, conditional logic -> create scenarios, spawn containers match requirements.

Build Image

Dockerfile in place -> build new image. Dockerfiles strict convention như Makefiles. Best: different image builds separate sub-directories. VD:

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

Command: -t repository name từ Dockerfile current directory (.). Simple/elegant.

Test Image

Run new container từ created image. Smoothly -> SSH connectivity + running Web server. Usual network rules apply.

Alternative Build

Knowledge do it own -> try official Apache builds. Docker repository contains good stuff, invest time check templates. Apache: chỉ cần Dockerfile sau (line 2 optional).

FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

COPY Instruction

Above: declaration template. COPY instruction: look public-html directory current folder, copy vào container during build. Same manner copy httpd.conf. Paths/filenames differ distro. Build image, run 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 '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

Many good reasons use technology. Briefly focus what gain running tiny isolated instances. Sure, lot happening under hood kernel, nhưng general: memory footprint spawned containers fairly small. Case: SSH + Apache containers dùng tiny fraction extra memory. Compare any virtualization technology.

Problems You May Encounter & Troubleshooting

Back to Apache example, learn why online tutorials sin copy-paste without checking, why most advice incorrect. Vấn đề: Apache server die within 1-2s sau launch container? Step into container troubleshoot. docker exec command attach shell instance.

docker exec -ti boring_mcclintock /bin/bash

Read logs, figure out wrong. httpd.conf configured correctly -> access/error logs /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

Typical problem: missing /run/httpd directory. Không exist container -> httpd start and die. Simple, nhưng few/any reference mentions.

Initially playing containers, encountered issue. Reading online: several suggestions, none really helped. But elaborate them, how make progress problem solving, even intermediate steps not useful.

Suggestion 1: Must use -D FOREGROUND run Apache, must use ENTRYPOINT not CMD. Difference subtle. Not solve problem.

ENTRYPOINT ["/usr/sbin/httpd"]
CMD ["-D", "FOREGROUND"]

Suggestion 2: Separate startup script work around issues starting/restarting httpd. Dockerfile becomes:

...
EXPOSE 80
COPY ./run-httpd.sh /run-httpd.sh
RUN chmod -v +x /run-httpd.sh
CMD ["/run-httpd.sh"]

Script contents:

#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND

Almost there. Remove old PID files, but normally not /run/httpd, thay vào đó /var/run/httpd. Không certain directory exists.

Idea: work around problems execution separation shell httpd thread spawned. Additional useful lessons COPY/RUN instructions, nhưng không fix issue.

Step 3 : EXPOSE 80
---> Using cache
---> 108785c8e507
Step 4 : COPY ./run-httpd.sh /run-httpd.sh
---> 582d795d59d4
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
Step 6 : CMD /run-httpd.sh
---> Running in f9c6b30795e2
---> b2dcc2818a27
Successfully built b2dcc2818a27

Won't work: apachectl unsupported command manage httpd, plus seen problems startup scripts/utilities earlier, fix 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 /etc/sysconfig/httpd config file.

Useful try different things, get hang of it. Highlights lack maturity/inadequate documentation technology.

Additional Commands

Many ways interact container. Không muốn attach new shell running instance -> subset docker commands directly against container ID/name:

docker

VD: top output container:

docker top boring_stallman

Too many images, some just testing -> remove free disk space. docker rmi command.

# docker rmi -f test7
Untagged: test7:latest
Deleted: d0505b88466a97b73d083434b2dd0e7b59b9a5e8d0438b1bf8c6c
Deleted: 5fc118f61bf856f6f3d90e0e71076b737fa7cc58cd56785ea7904
Deleted: 628c3d6b53992521c9c1fdda4148693347c3d10b1d130f7e091e7
Deleted: 58f11217c3e31206b4e41d07100a797cd4d17e4569b0fdb8b7a18
Deleted: 7505c70235e638c54028ea5b63eba2b691de6bee67c2cb5e2861a
...

Run containers background: -d flag, get shell prompt back. Useful nếu không mask signals, accidentally break shell -> kill container running foreground.

docker run -d -ti -p 80 image-3:latest

Check events, examine changes container filesystem, check history -> version control in place, export/import tarred images to/from remote locations (Web), more.

Differences Between exec and attach

Documentation: connect running container exec hoặc attach. Difference?

Official docs: docker exec runs new command in running container. Command started exec only runs while container primary process (PID 1) running, not restarted if container restarted.

Attach: attach running container using ID/name, view ongoing output hoặc control interactively. Attach same contained process multiple times simultaneously (screen sharing), hoặc quickly view progress daemonized process. Detach container (leave running) CTRL-p CTRL-q (quiet exit) hoặc CTRL-c (SIGKILL container). Attached container, exit main process -> process exit code returned client.

Nghĩa: attach -> shell, do whatever. Exec -> issue commands no interaction, nhưng use shell với exec -> same result as attach.

Differences Between start and run

Start: resume execution stopped container. Không dùng start fresh instance. Fresh instance: run command. Word choice could better.

Differences Between build and create

Build: create new image từ Dockerfile. Create: create new container dùng command line options/arguments. Create lets specify container settings (network configs, resource limitations, outside settings), affect container from outside. Build changes reflected inside once start instance. By start = run. Get it?

This Is Just A Beginning ...

Million more things: systemd enabled containers, policies, security, resource constraints, proxying, signals, other networking/storage (super-critical: mount data volumes inside containers so data không destroyed khi containers die), additional pure LXC commands, more. Barely scratched surface. But now know what to do. Get there. Slowly but surely.

More Reading

Recommend allocate few hours, spend honest time reading below detail. Then practice. Only way fully understand/embrace 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

Kết Luận

Done tutorial today. Hopefully useful. Nutshell: explain quite a few things: getting started Docker, pull images, run basic containers, add services SSH/Apache, commit changes, expose ports, build images Dockerfiles, troubleshooting problems, additional commands, more. Eventful và colorful.

Future: expand significantly learned here, focus helper technologies như supervisord, mount filesystems, administration/orchestration, many cool things. Docker nice concept, used correctly -> virtual world easier/elegant. Initial steps rough, nhưng guide provided right dose karma get happily/confidently underway. Ping me requests/desires. Technology related. Done.

P.S. Like article -> give love back Dedoimedo!

Cheers.