The New Features of RedHat 7
RHEL 7 has quite a few changes over it's predecessor. The most significant ones are explored here. If you're looking for more of an overview, see our blog article
systemd
systemd replaces the unix system V init / upstart system initialisation framework in previous RHEL releases. It is very different.
- gone: /etc/init.d scripts, service, chkconfig and runlevels (still available for compatibility but should not be used)
Instead of init.d scripts, systemd uses “service units” (files end with .service file extension)
systemctl command is used to stop/start/restart/enable/disable system services. When working with system services the .service extension can be omitted, e.g.
# systemctl stop bluetooth.service # systemctl stop bluetooth
both work
To check all services
# systemctl list-units --type service --all (- all service whatever state) UNIT LOAD ACTIVE SUB DESCRIPTION auditd.service loaded active running Security Auditing Service brandbot.service loaded inactive dead Flexible Branding Service cpupower.service loaded inactive dead Configure CPU power related settings crond.service loaded active running Command Scheduler dbus.service loaded active running D-Bus System Message Bus display-manager.service not-found inactive dead display-manager.service ....
To see just the running ones:
# systemctl list-units --type service UNIT LOAD ACTIVE SUB DESCRIPTION auditd.service loaded active running Security Auditing Service crond.service loaded active running Command Scheduler dbus.service loaded active running D-Bus System Message Bus getty@tty1.service loaded active running Getty on tty1 kdump.service loaded failed failed Crash recovery kernel arming kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current kernel lvm2-lvmetad.service loaded active running LVM2 metadata daemon lvm2-monitor.service loaded active exited Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling ..... LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 34 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'.
To check whether a service unit is enabled:
# systemctl list-unit-files --type service UNIT FILE STATE arp-ethers.service disabled auditd.service enabled auth-rpcgss-module.service static autovt@.service disabled blk-availability.service disabled brandbot.service static console-getty.service disabled console-shell.service disabled cpupower.service disabled crond.service enabled dbus-org.freedesktop.hostname1.service static ...
(N.B. for systemd a unit is a type of object it can control of which service is one. There's quite a few other unit types as we'll see later)
You can check dependencies:
systemctl list-dependencies
systemctl enable/disable does the job of chkconfig. e.g.
- chkconfig sshd on - systemctl enable sshd.service
- chkconfig sshd off - systemctl disable sshd.service
- chkconfig –list sshd - systemctl status sshd.service
e.g.
ip-10-51-72-53:root> #systemctl status sshd sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled) Active: active (running) since Thu 2016-02-18 14:05:44 GMT; 32min ago Main PID: 923 (sshd) CGroup: /system.slice/sshd.service +-923 /usr/sbin/sshd -D Feb 18 14:05:44 ip-10-51-72-53 systemd[1]: Started OpenSSH server daemon. Feb 18 14:05:44 ip-10-51-72-53 sshd[923]: Server listening on 0.0.0.0 port 22. Feb 18 14:05:44 ip-10-51-72-53 sshd[923]: Server listening on :: port 22. Feb 18 14:16:20 ip-10-51-72-53 sshd[2039]: Accepted password for tony from 10.44.163.107 port 36403 ssh2 Feb 18 14:28:46 ip-10-51-72-53 sshd[2111]: Accepted password for tony from 10.44.163.107 port 37930 ssh2
This is really nice, everything you need to know about a process from one command :)
When you enable a system service so that it is restarted on a reboot, the command reads the [Install] section for the service in /usr/lib/systemd/system/xxxx.service and creates a symbolic link in the appropriate /etc/systemd/system sub-directory. e.g. looking at sshd
/usr/lib/systemd/system/sshd.service has the following [Install] section
[Install] WantedBy=multi-user.target
and in /etc/systemd/system/multi-user.target.wants there's the following symbolic link
sshd.service -> /usr/lib/systemd/system/sshd.service
systemctl disable sshd - will remove the link
Targets are a group of units that can be grouped together based on dependencies and use the .target extension. Runlevels have been replaced by targets although a bunch of targets exist that correspond to the old runlevels for compatibility reasons:
Runlevel Target Units Description 0 runlevel0.target, poweroff.target Shut down and power off the system. 1 runlevel1.target, rescue.target Set up a rescue shell. 2 runlevel2.target, multi-user.target Set up a non-graphical multi-user system. 3 runlevel3.target, multi-user.target Set up a non-graphical multi-user system. 4 runlevel4.target, multi-user.target Set up a non-graphical multi-user system. 5 runlevel5.target, graphical.target Set up a graphical multi-user system. 6 runlevel6.target, reboot.target Shut down and reboot the system.
systemctl get-default - gives the default target
ip-10-51-72-53:root> #systemctl get-default multi-user.target
To get the currently loaded targets
To change the default target use: systemctl set-default name.target
This command replaces the symbolic link /etc/systemd/system/default.target to point to the new target in /usr/lib, e.g
ip-10-51-72-53:root> #pwd /etc/systemd/system ip-10-51-72-53:root> #ls -l total 4 drwxr-xr-x. 2 root root 30 Aug 21 2015 basic.target.wants lrwxrwxrwx. 1 root root 46 Aug 18 2015 dbus-org.freedesktop.NetworkManager.service -> /usr/lib/systemd/system/NetworkManager.service lrwxrwxrwx. 1 root root 57 Aug 18 2015 dbus-org.freedesktop.nm-dispatcher.service -> /usr/lib/systemd/system/NetworkManager-dispatcher.service lrwxrwxrwx. 1 root root 37 Aug 18 2015 default.target -> /lib/systemd/system/multi-user.target ....
If I wanted to change the target for this current session I could do the following:
systemctl isolate graphical.target (this replaces commands like telinit 5)
ip-10-51-72-53:root> #systemctl list-units --type target UNIT LOAD ACTIVE SUB DESCRIPTION basic.target loaded active active Basic System cryptsetup.target loaded active active Encrypted Volumes getty.target loaded active active Login Prompts local-fs-pre.target loaded active active Local File Systems (Pre) local-fs.target loaded active active Local File Systems multi-user.target loaded active active Multi-User System network.target loaded active active Network paths.target loaded active active Paths remote-fs.target loaded active active Remote File Systems slices.target loaded active active Slices sockets.target loaded active active Sockets swap.target loaded active active Swap sysinit.target loaded active active System Initialization timers.target loaded active active Timers LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 14 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'.
To change to rescue mode systemctl rescue or emergency mode systemctl emergency
Power management commands are also now called via systemctl:
Old Command New Command Description halt systemctl halt Halts the system. poweroff systemctl poweroff Powers off the system. reboot systemctl reboot Restarts the system. pm-suspend systemctl suspend Suspends the system. pm-hibernate systemctl hibernate Hibernates the system. pm-suspend-hybrid systemctl hybrid-sleep Hibernates and suspends the system.
However, the shutdown command can still be used to shutdown the server e.g. to shutdown at a certain time: shutdown –poweroff hh:mm
systemctl can also be used to interact with systemd on remote servers in the format (requires sshd running):
systemctl --host user_name@host_name command
To create a custom startup service, vi /etc/systemd/system/name.service , where name is the name of your process (it is recommended to create custom scripts in /etc/systemd/system rather the /usr/lib/systemd)
A typical (simple) entry will look like the following:
[Unit] Description=service_description After=network.target [Service] ExecStart=path_to_executable Type=forking PIDFile=path_to_pidfile [Install] WantedBy=default.target
Set permissions, chmod 644 /etc/systemd/system/name.service
systemctl daemon-reload systemctl start name.service
NOTE: ALWAYS RUN systemctl daemon-reload AFTER CREATTING NEW UNIT FILES OR MODIFYING THEM other systemctl start/enable commands could fail due to mismatches.
See http://0pointer.de/blog/projects/systemd-for-admins-3.html for example of converting init.d script
If you need to convert an existing unit file, for minor changes create a /etc/systemd/system/unit.d/ file with the amendments or for bigger changes copy file to /etc/systemd/system and update
Configuration files in /etc/systemd/system take precedence over /usr/lib/systemd/system
To display modified unit files
systemd-delta
Networking
With RHEL 7 the default networking service is NetworkManager. ifcfg config files are still supported but there are number of ways to interact with NetworkManager, nmtui, nmcli, control-center (gnome GUI) or nm-connection-editor. These apparently mean that you don't need to edit the config file anymore…
Some useful nmcli commands
ip-10-51-72-53:root> #nmcli con show NAME UUID TYPE DEVICE eth0 eaf52206-2f0c-441e-96b8-06c54f603b2f 802-3-ethernet -- System eth0 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03 802-3-ethernet eth0
ip-10-51-72-53:root> #nmcli dev status #DEVICE TYPE STATE CONNECTION eth0 ethernet connected System eth0 lo loopback unmanaged --
To configure an interface with nmcli
nmcli connection add type ethernet con-name connection-name ifname interface-name ip4 address gw4 address
A new type of network bonding is now available (RHEL 6 type bond is still available) called Network Teaming. This is supposed to have a lower overhead and has a modular design that can be interacted with via an API
to convert an existing bond: /usr/bin/bond2team –master bond0
To set up a new connection, nmtui is probably the easiest option, Edit a connection > Add , select Team on the New Connection screen and follow the prompts
Journald/rsyslog
Journald is part of systemd and can be used with or instead of rsyslogd. Usually only root can see all the messages but addinng a user to the adm group will allow that user to read the logs
- journalctl - shows the messages from all the log files in a format similiar to /var/log/messages
- journalctl -o verbose gibes detailed metadata about each message
- journalctl -f view in live mode (like tail -f)
- journalctl -p priority (priority corresponds to syslog levels e.g journalctl -p err - err and above)
- journalctl -b - messages since the last boot
- journalctl -p warning –since=“2016-1-1 00:00:01” messages this year
By default journald only stores the latest log entries in the non persistent /run/log/journal directory. syslog reads the journal logs and stores them in /var/log directory. Persistent logging can be be enabled and then rsyslog can be replaced. To enable persistent journal retention
mkdir -p /var/log/journal; systemctl restart systemd-journald
gnome-system-log provides a GUI to display log files
GRUB
grub2 is used in RHEL 7.
GRUB 2 has three main parts:
- /etc/default/grub - the file containing GRUB 2 menu settings.
- /etc/grub.d/ - the directory containing GRUB 2 menu creating scripts.
- /boot/grub/grub.cfg - the GRUB 2 configuration file, not editable.
As mentioned, grub.cfg shouldn't be edited as it's automatically built. RedHat recommended to use grubby for configuration
- grubby –default-kernel - lists the default kernel
- grubby –default-index - lists the default index
- grubby –info=ALL - list all kernel menu entries
To make changes, the format is
grubby --remove-args="argX argY" --args="argA argB" --update-kernel /boot/kernel
Scripts in /etc/grub.d examine the system and build the boot menu dependent on what is found automatically when the kernel is updated or a new one installed
NOTE: If GRUB_TIMEOUT is set to 0, no boot menu is displayed. To display it, press and hold any alphanumeric key when the BIOS info is displayed
/etc/default/grub specifies the default kernel which is usually saved:
ip-10-51-72-53:root> #cat /etc/default/grub GRUB_TIMEOUT=30 GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg00/lvswap rd.lvm.lv=vg00/lvroot rhgb quiet audit=1 console=ttyS0" GRUB_DISABLE_RECOVERY="true"
This points to the entry in /boot/grub2/grubenv with the saved_entries directive. This will be the latest installed kernel. You can change this using grub2-set-default e.g.
grub2-set-default 2
This will select the third “menuentry” line in grub.cfg ( remembering the first menu entry is 0 ). You can edit /etc/default/grub with this entry to make it a permanent. This will require a rebuild of grub.cfg
grub2-mkconfig -o /boot/grub2/grub.cfg
To add custom menu entries use /etc/grub.d/40_custom and add your script in there. This is the general format of an entry
#!/bin/sh -e echo "Some string" cat << EOF menuentry "Something" { set root=(hdX,Y) -- boot parameters -- } EOF
If grub breaks for some reason it can be reinstalled e.g.
grub2-install /dev/sda (assuming /boot is on /dev/sda)
To reset and reinstall (this clears all grub settings and configs)
1. rm /etc/grub.d/* 2. rm /etc/sysconfig/grub 3. grub2-mkconfig -o /boot/grub2/grub.cfg 4. grub2-install /dev/sda
NOTE: The procedure for EFI based servers is slightly different so don't forget to RTFM!!
To use the serial interface for grub boots
grubby --remove-args="rhgb quiet" --args=console=ttyS0,115200 --update-kernel=DEFAULT
This is just for the default kernel, you can also specify –update-kernel=ALL or a comma seperated list of kerne index numbers
If a new grub.cfg file is going to get built, update /etc/default/grub
GRUB_TERMINAL="serial" GRUB_SERIAL_COMMAND="serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1"
(adjust the serial settings according to your hardware)
then rebuild using grub2-mkconfig command
To boot into rescue mode, at the GRUB 2 boot screen, press e (for edit) and add the following to the linux16 line
systemd.unit=rescue.target
CTRL-a goes to start of line, CTRL-e to the end. Press CTRL-x to boot with the new parameter
To go to emergency add systemd.unit=emergency.target instead. For a debug shell add systemd.debug-shell
BRTFS & XFS
BRTFS is marked as a technology preview in RHEL 7 which I suppose is a bit like the Olympic games demonstration event, you can play as hard as you like but you won't win a medal.
Uses a COW style update that prevents filesystem corruption in the event of power failures. Features include built in RAID, multiple device support and online add/removal/replacement of devices. These features can remove the requirement for LVM. It is also said to have a lower overhead than LVM.
- mkfs.brtfs /dev/device - create a brtfs file system
- brtfs filesystem resize amount /mount-point - increase or decrease a brtfs filesystem
if the filesystem is made up of multiple devices, you need to specify the device to be increased, e.g.
# btrfs filesystem show /btrfstest Label: none uuid: 755b41b7-7a20-4a24-abb3-45fdbed1ab39 Total devices 4 FS bytes used 192.00KiB devid 1 size 1.00GiB used 224.75MiB path /dev/vdc devid 2 size 524.00MiB used 204.75MiB path /dev/vdd devid 3 size 1.00GiB used 8.00MiB path /dev/vde devid 4 size 1.00GiB used 8.00MiB path /dev/vdf # btrfs filesystem resize 2:+200M /btrfstest
brtfs filesystems can be made up of multiple devices and different raid configurations,e.g. setting up a raid10 fs
# mkfs.btrfs /dev/device1 /dev/device2 /dev/device3 /dev/device4
XFS is the new default filesystem. It can scale to 500TB and is billed as a high performance fs with quick recovery times.
Creating an xfs filesystem
mkfs.xfs /dev/device
Increasing a filesystem
xfs_growfs /mount-point -D size (where size in the size the filesystem will be grown to specified in blocks) xfs_growfs /mount-point -d (grows into whatever free space is available)
To repair a filesystem
xfs_repair/dev/device
XFS can be frozen so that consitent snapshots can be taken
xfs_freeze -f /mount-point (freeze) xfs_freeze -u /mount-point (unfreeze)
However, this isn't necessary if your using LVM snapshots as they'll do the the freezing for you. Which does beg the question as to how else you'd do a snapshot as there's no XFS utility. You can use the freeze/unfreeze with xfs_copy though (assuming you don't mind having your filesystem frozen for a while….)
There are xfsdump & xfsrestore utilities to back up and restore XFS filesystems
xfs_fsr - defrag filesystem xfs_admin - change filesystem parameters (must be unmounted)
Firewalld
iptables service has been replaced by firewalld in RHEL 7. It is a dynamic firewall, i.e. rules can be added or removed without having to restart it. It does actually use iptables commands to talk to kernel netfilter packet filter.
Uses the confusing (for me with my storage background) concept of zones. These are basically a set of rules. The pre-defined zones within firewalld are:
- drop: The lowest level of trust. All incoming connections are dropped without reply and only outgoing connections are possible.
- block: Similar to the above, but instead of simply dropping connections, incoming requests are rejected with an icmp-host-prohibited or icmp6-adm-prohibited message.
- public: Represents public, untrusted networks. You don't trust other computers but may allow selected incoming connections on a case-by-case basis.
- external: External networks in the event that you are using the firewall as your gateway. It is configured for NAT masquerading so that your internal network remains private but reachable.
- internal: The other side of the external zone, used for the internal portion of a gateway. The computers are fairly trustworthy and some additional services are available.
- dmz: Used for computers located in a DMZ (isolated computers that will not have access to the rest of your network). Only certain incoming connections are allowed.
- work: Used for work machines. Trust most of the computers in the network. A few more services might be allowed.
- home: A home environment. It generally implies that you trust most of the other computers and that a few more services will be accepted.
- trusted: Trust all of the machines in the network. The most open of the available options and should be used sparingly.
To start:
systemctl start firewalld.service firewall-cmd --state firewall-cmd --get-default-zone - find out which zone is currently selected, e.g. ip-10-51-72-53:root> #firewall-cmd --get-default-zone public
So what does “public” mean
ip-10-51-72-53:root> #firewall-cmd --list-all public (default, active) interfaces: eth0 sources: services: dhcpv6-client ssh ports: masquerade: no forward-ports: icmp-blocks: rich rules:
So the rule affects eth0 (the only interface on this server) and allows ssh and DHCP operations.
To find out about other available zones, to list zones:
ip-10-51-72-53:root> #firewall-cmd --get-zones block dmz drop external home internal public trusted work
To find out what one does:
ip-10-51-72-53:root> #firewall-cmd --zone=home --list-all home interfaces: sources: services: dhcpv6-client ipp-client mdns samba-client ssh ports: masquerade: no forward-ports: icmp-blocks: rich rules:
You could specify this zone to be the active one as follows:
firewall-cmd --zone=home --change-interface=eth0
If you now rebooted the server, it would change back to the default zone. To make this permanent you could update ifcfg-eth0 script, e.g.
DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp TYPE=Ethernet ZONE=home
If you want to customise a zone, you can get a list of predefined services as follows:
ip-10-51-72-53:root> #firewall-cmd --get-services RH-Satellite-6 amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind samba samba-client smtp ssh telnet tftp tftp-client transmission-client vnc-server wbem-https
(if you need more information about what these mean, check the corresponding xml file in /usr/lib/firewalld/services)
To add a serivce
firewall-cmd --zone=public --add-service=https
if this is working as planned, make the change permanent
sudo firewall-cmd --zone=public --permanent --add-service=https
For bespoke services that do not have a predefined service, use the port number e.g.:
firewall-cmd --zone=public --add-port=9100/tcp
or a range
firewall-cmd --zone=public --add-port=9100-9999/udp
if they're working OK, don't forget to make them permanent!
firewall-cmd --zone=public --permanent --add-port=9100-9102/udp
If you want to define a service, rather than use port number (which makes it easier to remember whet they're for later), copy an existing service and edit it
cp /usr/lib/firewalld/services/ftp.xml /etc/firewalld/services/my-bespoke-service.xml
(Note: similiar to systemd, you don't make changes in the system defined location but in a folder in /etc )
vi /etc/firewalld/services/my-bespoke-service.xml
<?xml version="1.0" encoding="utf-8"?> <service> <short>Bespoke</short> <description>A bespoke service that doesn't do anything useful at all</description> <port protocol="udp" port="9100"/> <port protocol="udp" port="9101"/> <port protocol="udp" port="9101"/> </service>
Then reload the firewall
firewall-cmd --reload; firewall-cmd --get-services
service bespoke should now be listed. You can then add it to your zone as required.
To create a custom zone:
firewall-cmd --permanent --new-zone=myZone
This will obviously contain nothing yet, so add some services:
firewall-cmd --zone=myZone --add-service=ssh firewall-cmd --zone=myZone --add-service=http firewall-cmd --zone=myZone --add-service=https
Assign it to an interface
firewall-cmd --zone=myZone --change-interface=eth0
If all is well, make the changes permanent
firewall-cmd --zone=myZone --permanent --add-service=ssh firewall-cmd --zone=myZone --permanent --add-service=http firewall-cmd --zone=myZone --permanent --add-service=https
And edit ifcfg-eth0
DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp TYPE=Ethernet ZONE=myZone
Restart network & firewall
systemctl restart network systemctl restart firewalld
And check
firewall-cmd --get-active-zones firewall-cmd --zone=myZone --list-services
Now you're all sorted, you'll probably want the firewall to restart on boot
systemctl enable firewalld
This section (firewalld) is based on this excellent Digitalocean page: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-centos-7
Time
timedatectl can be used to show and control time zones
tony@ip-10-51-72-53 ~]$ timedatectl Local time: Wed 2016-03-02 12:49:41 GMT Universal time: Wed 2016-03-02 12:49:41 UTC Timezone: Europe/London (GMT, +0000) NTP enabled: yes NTP synchronized: no RTC in local TZ: no DST active: no Last DST change: DST ended at Sun 2015-10-25 01:59:59 BST Sun 2015-10-25 01:00:00 GMT Next DST change: DST begins (the clock jumps one hour forward) at Sun 2016-03-27 00:59:59 GMT Sun 2016-03-27 02:00:00 BST
NTP remains the default time synchronisation package for servers, config file is still /etc/ntp.conf
To set the date from NTP
# systemctl stop ntpd # ntpdate pool.ntp.org 5 Jul 10:36:58 ntpdate[2190]: adjust time server 95.81.173.74 offset -0.005354 sec # systemctl start ntpd
For mobile and virtual systems, the new chrony service is recommended. This is because chronyd can tolerate time sources being unavailable for periods of time. It is also faster than ntpd. However ntpd is fully compliant with NTP version 4 standard and has many drivers for reference clocks. the package can be installed using yum in the usual way and enabled & started using systemctl enable chronyd; systemctl start chronyd
The config file is /etc/chrony.conf.
To get information about the time reference:
# chronyc tracking Reference ID : 94.23.44.157 (merzhin.deuza.net) Stratum : 3 Ref time (UTC) : Thu Jul 3 22:26:27 2014 System time : 0.000265665 seconds fast of NTP time Last offset : 0.000599796 seconds RMS offset : 3619.895751953 seconds Frequency : 0.070 ppm slow Residual freq : 0.012 ppm Skew : 0.164 ppm Root delay : 0.030609 seconds Root dispersion : 0.005556 seconds Update interval : 1026.9 seconds Leap status : Normal
chronyc sources -v is the equivalent of ntpq command
Also available is PTP, Precision Time Protocol. This is capable of sub microsecond accuracy (better that NTP). With PTP capable NICs and switches, PTP can account for delays in the message transfer giving much greater accuracy. To check for NIC PTP support use ethtool, e.g.
ethtool -T eth0
If time stamping you should see either
SOF_TIMESTAMPING_SOFTWARE SOF_TIMESTAMPING_TX_SOFTWARE SOF_TIMESTAMPING_RX_SOFTWARE
For software time stamping or
SOF_TIMESTAMPING_RAW_HARDWARE SOF_TIMESTAMPING_TX_HARDWARE SOF_TIMESTAMPING_RX_HARDWARE
For hardware time stamping
Config file is /etc/ptp4l.conf To start
systemctl start ptp4l
Docker
Not really an integral part of RHEL 7 but it is now bundled with RHEL 7. This container technology provides a kind of cut down VM that has become very popular in devops environments.
To start: systemctl enable docker && systemctl start docker
Now you can use docker commands:
- docker version - version information
- docker info - information about your docker installation
e.g.
MicroServer # docker info Containers: 3 Running: 0 Paused: 0 Stopped: 3 Images: 56 Server Version: 1.2.0 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 64 Dirperm1 Supported: false Execution Driver: native-0.2 Logging Driver: json-file Plugins: Volume: local Network: null host bridge Kernel Version: 3.10.0-123.9.3.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 7.798 GiB Name: MicroServer ID: Y6RN:6GUX:R3VH:URX2:DUGW:NASS:XJCP:EPRZ:YCII:MKIK:7S7S:HMSJ WARNING: No swap limit support
The info shows that I already have 3 containers, all of which are stopped. To check what I have
MicroServer ~ # docker images REPOSITORY TAG IMAGE ID CREATED SIZE phpwithmysql v2 b5a8a29f293e 5 months ago 483.7 MB phpwithmysql latest d206203dd8ea 5 months ago 483.7 MB wordpress latest ba297914d5df 5 months ago 512.3 MB php 5.6-apache e0cd35a1d2d5 5 months ago 480.7 MB mysql 5.7 93220007617a 5 months ago 321.2 MB hello-world latest 0ebda6c3e276 10 months ago 910 B
Confusing, because that lists 6 images. That's because an image only becomes a container when you run it. To check my containers:
MicroServer ~ # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e477da63b574 wordpress "/entrypoint.sh apach" 5 months ago Exited (0) 5 months ago docker_web_1 a1b2a664086e mysql:5.7 "/entrypoint.sh mysql" 5 months ago Exited (0) 5 months ago docker_mysql_1 7d4a1601f379 hello-world "/hello" 8 months ago Exited (0) 8 months ago prickly_babbage
As can be seen, I haven't used either the containers or images for 5 months so of course I can't remember what I was doing with them. Luckily I can use docker inspect to see what's in the image, e.g.
docker inspect phpwithmysql
This shows the latest image, the key parts of which are
.... "ExposedPorts": { "80/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "PHP_INI_DIR=/usr/local/etc/php", "PHP_EXTRA_BUILD_DEPS=apache2-dev", "PHP_EXTRA_CONFIGURE_ARGS=--with-apxs2", "GPG_KEYS=0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3", "PHP_VERSION=5.6.13" ], "Cmd": [ "/bin/sh", "-c", "#(nop) CMD [\"apache2-foreground\"]" ], "Image": "3adfa294d123ed1942416061687454cb69c690684189ad548d00ea97b2d197a6", "Volumes": null, "WorkingDir": "/var/www/html", "Entrypoint": null, "OnBuild": [], "Labels": {}
So if I launched the image as a container it will execute apache with PHP enabled using /var/www/html as the document root. Port 80 will be an open port in the container. so lets try running it:
MicroServer docker # docker run phpwithmysql AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.1. Set the 'ServerName' directive globally to suppress this message AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.1. Set the 'ServerName' directive globally to suppress this message [Fri Mar 04 12:43:46.297483 2016] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.13 configured -- resuming normal operations [Fri Mar 04 12:43:46.297701 2016] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
Now a new network interface has appeared:
MicroServer ~ # ifconfig -a docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99 inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:44 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:536 (536.0 B) TX bytes:11611 (11.6 KB)
And if I point my browser at this IP address I see the index.html page in /var/www/html
Useful commands to check out your docker instance:
MicroServer ~ # docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d34d4890b473 phpwithmysql "apache2-foreground" 6 minutes ago Up 6 minutes 80/tcp kickass_williams
MicroServer ~ # docker logs d34d4890b473 AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.1. Set the 'ServerName' directive globally to suppress this message AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.1. Set the 'ServerName' directive globally to suppress this message [Fri Mar 04 12:43:46.297483 2016] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.13 configured -- resuming normal operations [Fri Mar 04 12:43:46.297701 2016] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
MicroServer ~ # docker stop d34d4890b473 d34d4890b473
MicroServer docker # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d34d4890b473 phpwithmysql "apache2-foreground" 34 minutes ago Exited (0) 4 minutes ago kickass_williams e477da63b574 wordpress "/entrypoint.sh apach" 5 months ago Exited (0) 5 months ago docker_web_1 a1b2a664086e mysql:5.7 "/entrypoint.sh mysql" 5 months ago Exited (0) 5 months ago docker_mysql_1 7d4a1601f379 hello-world "/hello" 8 months ago Exited (0) 8 months ago prickly_babbage
I don't want the hello-world container any more, it was a bit boring:
MicroServer docker # docker rm 7d4a1601f379 7d4a1601f379 MicroServer docker # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d34d4890b473 phpwithmysql "apache2-foreground" 35 minutes ago Exited (0) 26 minutes ago kickass_williams e477da63b574 wordpress "/entrypoint.sh apach" 5 months ago Exited (0) 5 months ago docker_web_1 a1b2a664086e mysql:5.7 "/entrypoint.sh mysql" 5 months ago Exited (0) 5 months ago docker_mysql_1 MicroServer docker #
Docker run a repository of prebuilt images, to search:
MicroServer docker # docker search coreos NAME DESCRIPTION STARS OFFICIAL AUTOMATED bhuisgen/docker-zabbix-coreos Zabbix agent for CoreOS server 9 [OK] radial/coreos-pxe Spoke container for running dnsmasq as PXE... 6 [OK] million12/linode-coreos-api Deploy CoreOS on Linode. 3 [OK] centurylink/coreos-cli-wetty This image provides a Wetty terminal with ... 2 [OK] olalond3/coreos-bitcoind coreos bitcoind 2 [OK] ccll/coreos-pypy 1 [OK] steigr/coreos CoreOS Docker Container 1 pingles/consul-coreos 1 [OK] shift/coreos-ubuntu-etcd 1 [OK] christianbladescb/newrelic-coreos Run newrelic's sysmond in a container on C... 1 [OK] allen13/coreos-ansible-toolbox Control CoreOS boxes with ansible using a ... 1 [OK] gregsymons/zookeeper-coreos 1 [OK] pablocouto/coreos-sshguard sshguard for CoreOS 1 [OK] tleyden5iwx/sync-gateway-coreos 1 [OK] yummly/consul-coreos Consul using etcd on CoreOS for bootstrap.... 0 [OK] geowa4/coreos-toolbox Replace the default toolbox image on CoreO... 0 [OK] docku/pxe-coreos 0 [OK] majidaldoiongithub/coreos-nvidia run privileged to install nvidia and cuda ... 0 [OK] shift/coreos-ubuntu-confd 0 [OK] zumbrunnen/coreos-gce Google Cloud SDK for CoreOS. Useful for dy... 0 [OK] nizq/docker-pfq-build-coreos A docker image for building pfq kernel mod... 0 [OK] havardline/coreos This code is not ready for production. The... 0 [OK] andrewrothstein/coreos-ipxeserver flask based webserver for hosting artifact... 0 [OK] alino/coreos-mongodb-cluster mongo 3.0 0 [OK] chriskite/mesos-on-coreos 0 [OK] MicroServer docker #
To get an image
MicroServer docker # docker pull centos Using default tag: latest latest: Pulling from library/centos a3ed95caeb02: Pull complete a07226856d92: Pull complete Digest: sha256:1272ae53bac7bf054dd209a0b4a8629bcc39526c2a767427c7639b630a224a9e Status: Downloaded newer image for centos:latest MicroServer docker #
To run it
MicroServer docker # docker run -t -i centos /bin/bash [root@3b596dff0087 /]# ls anaconda-post.log bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
I'm going to install git
[root@3b596dff0087 /]# yum install git Loaded plugins: fastestmirror, ovl Loading mirror speeds from cached hostfile * base: mirror.econdc.com * extras: mirror.as29550.net * updates: mirror.ukhost4u.com Resolving Dependencies --> Running transaction check ---> Package git.x86_64 0:1.8.3.1-6.el7 will be installed --> Processing Dependency: perl-Git = 1.8.3.1-6.el7 for package: git-1.8.3.1-6.el7.x86_64 .... .... [root@3b596dff0087 /]# ls /usr/bin/git /usr/bin/git [root@3b596dff0087 /]#
Now I want to save my centos image + git
MicroServer docker # docker commit -m "Added git" -a AnthonyJDavis 3b596dff0087 centos-with-git sha256:37533ba9a45af5a44c03aa9a2b57c0641768aade3042e8315e26c44796468bdf MicroServer docker # docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos-with-git latest 37533ba9a45a 14 seconds ago 318.8 MB centos latest 0f0be3675ebb 2 weeks ago 196.6 MB phpwithmysql v2 b5a8a29f293e 5 months ago 483.7 MB phpwithmysql latest d206203dd8ea 5 months ago 483.7 MB wordpress latest ba297914d5df 5 months ago 512.3 MB php 5.6-apache e0cd35a1d2d5 5 months ago 480.7 MB mysql 5.7 93220007617a 5 months ago 321.2 MB hello-world latest 0ebda6c3e276 10 months ago 910 B MicroServer docker #
I want to change the tag
MicroServer docker # docker tag 37533ba9a45a test MicroServer docker # docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos-with-git latest 37533ba9a45a 2 minutes ago 318.8 MB test latest 37533ba9a45a 2 minutes ago 318.8 MB centos latest 0f0be3675ebb 2 weeks ago 196.6 MB phpwithmysql v2 b5a8a29f293e 5 months ago 483.7 MB phpwithmysql latest d206203dd8ea 5 months ago 483.7 MB wordpress latest ba297914d5df 5 months ago 512.3 MB php 5.6-apache e0cd35a1d2d5 5 months ago 480.7 MB mysql 5.7 93220007617a 5 months ago 321.2 MB hello-world latest 0ebda6c3e276 10 months ago 910 B
Oops, made a mistake, let's get rid of test
MicroServer docker # docker rmi test Untagged: test:latest
And do it the right way
MicroServer docker # docker tag 37533ba9a45a centos-with-git:test MicroServer docker # docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos-with-git latest 37533ba9a45a 3 minutes ago 318.8 MB centos-with-git test 37533ba9a45a 3 minutes ago 318.8 MB centos latest 0f0be3675ebb 2 weeks ago 196.6 MB phpwithmysql v2 b5a8a29f293e 5 months ago 483.7 MB phpwithmysql latest d206203dd8ea 5 months ago 483.7 MB wordpress latest ba297914d5df 5 months ago 512.3 MB php 5.6-apache e0cd35a1d2d5 5 months ago 480.7 MB mysql 5.7 93220007617a 5 months ago 321.2 MB hello-world latest 0ebda6c3e276 10 months ago 910 B
And that's the highlights of the new features of RHEL7 . There are lots of other minor changes of course but I think this covers the main features. As already mentioned, an overview is available in our blog
Recent Changes
Contribute to this wiki
Why not help others by sharing your knowledge? Contribute something to this wiki and
join out hall of fame!
Contact us for a user name and password