Figure 3-1 illustrates a simplified SONiC container startup sequence. First, systemd reads the service unit files and evaluates their dependency and ordering directives. It then starts docker.service, making the Docker daemon available. After that, SONiC service containers are started according to the dependencies and ordering rules defined in their service unit files.
In this simplified example, database.service starts early because many SONiC services rely on the Redis databases to exchange configuration, state, and event information. Services such as pmon, syncd, and swss are then started according to their own dependencies and ordering rules. Higher-level SONiC service containers, such as bgp, lldp, teamd, and snmp, are started after the lower-level services they depend on are available.
It is also important to distinguish between host-level service management and process management inside containers. systemd is responsible for starting the host-level service units that create and manage SONiC service containers. After a container has started, the processes inside the container are launched and supervised by the container's own initialization logic, which in many SONiC containers is based on supervisord. For example, after the bgp container has started, processes such as bgpd, zebra, and fpmsyncd are started inside the container. Similarly, the swss container starts and supervises its own processes after the container has been created.
Figure 3-1: High-Level Overview of the SONiC Container Startup Process.
The following examples show how this startup model is expressed in actual systemd service unit files. Examples 3-1, 3-2, and 3-3 focus on docker.service, database.service, and pmon.service because they illustrate the relationship between the Docker Engine, the SONiC database container, and a platform management container.
Docker – Container Engine Foundation
Example 3-1 shows a simplified docker.service unit file. This service starts the Docker daemon (dockerd), which provides the Docker Engine used to create and manage SONiC service containers. SONiC service containers cannot be created or started until the Docker daemon is available. For that reason, many SONiC service unit files declare an explicit dependency on docker.service.
In the [Unit] section, Requires= creates a strong dependency on containerd.service. When docker.service is started, systemd also pulls in containerd.service. The After= directive defines startup ordering by specifying that docker.service is started after network-online.target, firewalld.service, and containerd.service. The Wants= directive expresses a weaker dependency on network-online.target. systemd attempts to start the target, but a failure of that target does not have the same effect as a failed required dependency.
The [Service] section defines the service lifecycle. In this example, ExecStart= starts dockerd, Type=notify tells systemd that the daemon will notify systemd when it is ready, and Restart=always together with RestartSec=2 instructs systemd to restart the Docker daemon after a short delay if it exits unexpectedly.
[Unit]
Description=Docker Application Container Engine
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=containerd.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
Example 3-1: Unit File Example – Docker Engine Service.
Database – Redis Database Container
Example 3-2 shows the database.service unit that starts the SONiC database container. The [Unit] section declares Requires=docker.service and After=docker.service, which means that Docker is both required and ordered to start before the database service. The Before= directive orders database.service before services such as swss.service, syncd.service, bgp.service, and lldp.service. This is consistent with the SONiC architecture because many SONiC services rely on the Redis databases to exchange configuration, state, and event information.
In the [Service] section, Type=oneshot tells systemd that the service performs a finite task rather than running continuously. RemainAfterExit=yes keeps the service in the active state after the start command has completed, allowing other services to recognize that the database container has already been initialized.
[Unit]
Description=SONiC database container
Requires=docker.service
After=docker.service
Before=swss.service syncd.service bgp.service lldp.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/docker-sonic-db start
ExecStop=/usr/local/bin/docker-sonic-db stop
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
Example 3-2: Unit File Example – SONiC Database Container Service.
PMON – Platform Monitor Container
Example 3-3 shows the pmon.service unit. The [Unit] section declares Requires=docker.service database.service together with After=docker.service database.service, ensuring that Docker and the database service are both available before pmon.service is started. The Before= directive orders pmon.service before selected services, including swss.service and bgp.service.
This ordering is consistent with the role of the pmon container, which provides platform management functions such as monitoring hardware sensors, fans, power supplies, LEDs, and transceivers. It also publishes platform state that can be used by other SONiC services.
[Unit]
Description=SONiC pmon container
Requires=docker.service database.service
After=docker.service database.service
Before=swss.service bgp.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/docker-pmon start
ExecStop=/usr/local/bin/docker-pmon stop
ExecReload=/usr/local/bin/docker-pmonreload
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Example 3-3: Unit File Example – SONiC pmon Container Service.
Verifications
This section shows how to verify the SONiC boot process from the Linux command line. The following services are verified using the same three-step approach. The following services are verified using the same three-step approach. First, systemctl status verifies the host-level service state. Second, systemctl cat shows the dependency and ordering relationships defined in the service unit. Finally, docker exec is used to run supervisorctl status inside the container to verify that the expected processes are running. Together, these commands provide a practical way to connect the boot sequence described earlier in this chapter to the actual runtime state of a SONiC switch.
Docker – Container Engine
The first component to verify is the Docker service, because Docker provides the container engine used by the SONiC service units. If docker.service is not active, SONiC service containers cannot be created or started. In the status output, the most useful fields are Loaded, Active, Drop-In, and Main PID.
admin@sonic:~$ systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset>
Drop-In: /etc/systemd/system/docker.service.d
└─docker.service.conf
Active: active (running) since Wed 2026-07-01 07:59:53 UTC; 17min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 711 (dockerd)
Tasks: 40
Memory: 158.8M
CGroup: /system.slice/docker.service
└─711 /usr/bin/dockerd --experimental -H unix:// --storage-driver=>
admin@sonic:~$
Example 3-4: Docker - systemctl status docker.service.
The output shows that docker.service is loaded and active. The main process is dockerd, which confirms that the Docker daemon is running on the host. The drop-in file also shows that the effective Docker configuration may include SONiC- or platform-specific overrides in addition to the default unit file.
After confirming that Docker is running, the effective unit file can be inspected with systemctl cat. This is useful because it shows both the original unit file and any drop-in configuration files that modify the service behavior. When reading this output, focus on dependency directives such as Requires=, ordering directives such as After=, and the final ExecStart= command used to launch the Docker daemon.
admin@sonic:~$ systemctl cat docker.service
# /lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service containerd.ser>
Wants=network-online.target
Requires=docker.socket containerd.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/docker.service.d/docker.service.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --experimental -H unix:// --storage-driver=overlay2 >
Example 3-5: Docker - systemctl cat docker.service.
In this example, the drop-in configuration clears the original ExecStart line and replaces it with a SONiC-specific Docker daemon command. This is an important detail because troubleshooting should be based on the effective unit file, not only on the default file installed by the operating system package
.
Database – Redis Database Container
The database container is one of the most important services to verify during boot because many SONiC components exchange configuration, state, counters, and events through Redis databases. A problem in database.service can prevent higher-level services from starting correctly or from exchanging state after they have started.
admin@sonic:~$ systemctl status database.service
● database.service - Database container
Loaded: loaded (/lib/systemd/system/database.service; enabled; vendor pres>
Active: active (running) since Wed 2026-07-01 08:00:02 UTC; 28min ago
Process: 1075 ExecStartPre=/usr/bin/database.sh start (code=exited, status=>
Main PID: 1973 (database.sh)
Tasks: 2 (limit: 4289)
Memory: 3.1M
CGroup: /sonic.slice/sonic-core.slice/database.service
├─1973 /bin/bash /usr/bin/database.sh wait
└─2010 tail --pid=1144 -f /dev/null
Example 3-6: Database - systemctl status database.service.
The status output shows that database.service is active. The service is represented on the host by the database.sh helper script, while the actual Redis processes run inside the database container. This is a typical SONiC pattern: systemd manages the container service at the host level, and the processes inside the container are managed separately.
admin@sonic:~$ systemctl cat database.service
# /lib/systemd/system/database.service
[Unit]
Description=Database container
Wants=database-chassis.service
After=database-chassis.service
Requires=docker.service
After=docker.service
After=rc-local.service
StartLimitIntervalSec=1200
StartLimitBurst=3
[Service]
User=root
ExecStartPre=/usr/bin/database.sh start
ExecStart=/usr/bin/database.sh wait
ExecStop=/usr/bin/database.sh stop
Restart=always
RestartSec=30
Slice=sonic-core.slice
[Install]
WantedBy=multi-user.target
Example 3-7: Database - systemctl cat database.service.
The unit file confirms that database.service requires docker.service and is ordered after it. The ExecStartPre command starts the database container, and the ExecStart command waits for the container process to remain available. This explains why database.service can appear as an active host-level service even though the important Redis processes are running inside the container.
To verify the internal state of the database container, use supervisorctl status inside the container. This command shows the processes that supervisord manages inside the container. In this example, several Redis processes are running, which is normal on SONiC systems that use a multi-Redis model.
admin@sonic:~$ docker exec -it database supervisorctl status
flushdb EXITED Jul 01 08:00 AM
redis RUNNING pid 71, uptime 0:42:32
redis2 RUNNING pid 72, uptime 0:42:32
redis3 RUNNING pid 75, uptime 0:42:32
redis4 RUNNING pid 77, uptime 0:42:32
redis6 RUNNING pid 80, uptime 0:42:32
rediswb RUNNING pid 82, uptime 0:42:32
restart-rsyslogd EXITED Jul 01 08:01 AM
rsyslogd RUNNING pid 247, uptime 0:41:03
supervisor-proc-exit-listener RUNNING pid 69, uptime 0:42:32
Example 3-8: Database - docker exec -it database supervisorctl status.
Several Redis processes are shown because this SONiC image uses multiple Redis instances inside the database container. Instead of placing all logical databases behind a single Redis process, SONiC can split database workloads across separate Redis servers. A typical deployment may keep slower management-oriented databases, such as CONFIG_DB and STATE_DB, in the main redis instance, place hardware-programming data such as ASIC_DB in a separate instance such as redis2, move high-frequency telemetry data such as COUNTERS_DB to another instance such as redis3, and use a dedicated write-back instance such as rediswb for write-back-related databases. Other instances, such as redis4 or redis6, may be used for additional database groups depending on the SONiC image, platform, and enabled feature set. The exact database-to-instance mapping should therefore be verified from the database configuration files on the running system rather than assumed from the process names alone.
The output shows that the Redis instances are running and that one-shot initialization tasks such as flushdb and restart-rsyslogd have exited. An EXITED state is not automatically an error; it can be expected for processes that are designed to run once during startup and then terminate. The important point is to distinguish long-running daemons, such as Redis, from short-lived initialization tasks.
Note: When reading supervisord output, RUNNING usually means that the daemon is active, EXITED can be normal for one-shot initialization tasks, and STOPPED can be normal for optional processes that are not started in the current environment. A FATAL state usually requires further investigation, especially if the process is expected to run on the platform or in the selected feature configuration.
SWSS – Switch State Service
The SWSS container is central to the SONiC control-plane pipeline. It contains orchestration and synchronization processes that consume application state from Redis databases and translate it toward the hardware-oriented state used by syncd. For that reason, swss.service is one of the key services to verify after the database container has started.
admin@sonic:~$ systemctl status swss.service
● swss.service - switch state service
Loaded: loaded (/lib/systemd/system/swss.service; enabled; vendor preset: >
Active: active (running) since Wed 2026-07-01 11:38:29 UTC; 2min 38s ago
Process: 1910 ExecStartPre=/usr/local/bin/swss.sh start (code=exited, statu>
Main PID: 2894 (swss.sh)
Tasks: 5 (limit: 4289)
Memory: 28.3M
CGroup: /sonic.slice/sonic-core.slice/swss.service
├─2894 /bin/bash /usr/local/bin/swss.sh wait
└─8228 python3 /usr/bin/docker-wait-any -s swss -d syncd teamd -t >
Example 3-9: SWSS - systemctl status swss.service.
The status output confirms that swss.service is active from the host systemd viewpoint. The service is represented by the swss.sh helper script, which waits for the container process. This confirms that the host-level service is running, but it does not by itself prove that all orchestration processes inside the container are healthy.
admin@sonic:~$ systemctl cat swss.service
# /lib/systemd/system/swss.service
[Unit]
Description=switch state service
Requires=database.service
After=database.service
Requires=updategraph.service
After=updategraph.service
#After=interfaces-config.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
StartLimitIntervalSec=1200
StartLimitBurst=20
[Service]
User=root
Environment=sonic_asic_platform=vs
ExecStartPre=/usr/local/bin/swss.sh start
ExecStart=/usr/local/bin/swss.sh wait
ExecStop=/usr/local/bin/swss.sh stop
Restart=always
RestartSec=30
Slice=sonic-core.slice
[Install]
WantedBy=sonic.target
admin@sonic:~$
Example 3-10: SWSS - systemctl cat swss.service.
The unit file shows that swss.service requires database.service and is ordered after it. This reflects the fact that SWSS consumes database state during startup and runtime. The service is also bound to sonic.target, which means it participates in the normal SONiC startup target rather than being an isolated host service.
admin@sonic:~$ docker exec -it swss supervisorctl status
aclsvcd RUNNING pid 340, uptime 0:02:45
arsmgrd RUNNING pid 325, uptime 0:02:46
buffermgrd RUNNING pid 319, uptime 0:02:47
coppmgrd RUNNING pid 310, uptime 0:02:48
delay-restore EXITED Jul 01 11:38 AM
dependent-startup EXITED Jul 01 11:39 AM
enable_counters EXITED Jul 01 11:39 AM
evpnmhmgrd RUNNING pid 332, uptime 0:02:46
fdbsyncd RUNNING pid 336, uptime 0:02:45
gearsyncd EXITED Jul 01 11:38 AM
intfmgrd RUNNING pid 314, uptime 0:02:47
iphelpermgrd RUNNING pid 363, uptime 0:02:44
loopbackmgrd RUNNING pid 316, uptime 0:02:47
nbrmgrd RUNNING pid 328, uptime 0:02:46
neighsyncd RUNNING pid 311, uptime 0:02:48
orchagent RUNNING pid 253, uptime 0:02:57
portmgrd RUNNING pid 315, uptime 0:02:47
portsyncd RUNNING pid 168, uptime 0:02:59
ptp_1_d FATAL Exited too quickly
restart-rsyslogd EXITED Jul 01 11:39 AM
restore_neighbors EXITED Jul 01 11:39 AM
rsyslogd RUNNING pid 712, uptime 0:01:44
supervisor-proc-exit-listener RUNNING pid 20, uptime 0:03:05
switchmgrd RUNNING pid 318, uptime 0:02:47
swssconfig EXITED Jul 01 11:38 AM
swsswait EXITED Jul 01 11:39 AM
tunnelmgrd RUNNING pid 338, uptime 0:02:45
vlanmgrd RUNNING pid 312, uptime 0:02:48
vrfmgrd RUNNING pid 320, uptime 0:02:47
vxlanmgrd RUNNING pid 333, uptime 0:02:46
admin@sonic:~$
Example 3-11: SWSS - docker exec -it swss supervisorctl status.
In the SWSS supervisor output, processes such as orchagent, portsyncd, neighsyncd, intfmgrd, and several manager daemons are running. These processes represent the internal work performed by the SWSS container after systemd has started the host-level service. Any FATAL process should be interpreted in context. For example, a PTP-related process may fail in a lab or virtual environment where the required platform support is not available.
PMON – Platform Monitor
The pmon container provides platform monitoring functions. Depending on the platform, it may monitor hardware sensors, fans, power supplies, transceivers, EEPROM information, and other platform-specific components. In virtual or lab environments, some platform-related helper processes may exit because the corresponding hardware is not present.
admin@sonic:~$ systemctl status pmon.service
● pmon.service - Platform monitor container
Loaded: loaded (/lib/systemd/system/pmon.service; enabled; vendor preset: >
Active: active (running) since Wed 2026-07-01 08:00:40 UTC; 29min ago
Process: 4405 ExecStartPre=/usr/bin/pmon.sh start (code=exited, status=0/SU>
Main PID: 6301 (pmon.sh)
Tasks: 2 (limit: 4289)
Memory: 1.6M
CGroup: /system.slice/pmon.service
├─6301 /bin/bash /usr/bin/pmon.sh wait
└─6671 tail --pid=6229 -f /dev/null
admin@sonic:~$
Example 3-12: PMON - systemctl status pmon.service.
The output indicates that pmon.service is active at the host level. As with other SONiC containers, systemd is waiting on the helper script rather than directly supervising every process inside the container. The internal platform-monitoring processes must therefore be checked separately with supervisorctl status.
admin@sonic:~$ systemctl cat pmon.service
# /lib/systemd/system/pmon.service
[Unit]
Description=Platform monitor container
Requires=database.service updategraph.service swss.service
After=database.service updategraph.service swss.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
StartLimitIntervalSec=1200
StartLimitBurst=20
[Service]
User=admin
ExecStartPre=/usr/bin/pmon.sh start
ExecStart=/usr/bin/pmon.sh wait
ExecStop=/usr/bin/pmon.sh stop
Restart=always
RestartSec=30
TimeoutStartSec=360
[Install]
WantedBy=sonic.target swss.service
Example 3-13: PMON - systemctl cat pmon.service.
The unit file shows that pmon.service depends on database.service, updategraph.service, and swss.service. This ordering is important because platform monitoring may need database access and system state before its internal processes can operate correctly. The WantedBy line also shows that PMON is associated with both the SONiC startup target and SWSS-related startup.
admin@sonic:~$ docker exec -it pmon supervisorctl status
dependent-startup EXITED Jul 01 08:01 AM
i2cstatsd EXITED Jul 01 08:01 AM
monitpmon EXITED Jul 01 08:01 AM
restart-rsyslogd EXITED Jul 01 08:01 AM
rsyslogd RUNNING pid 222, uptime 0:41:22
ssdhealthd RUNNING pid 73, uptime 0:41:48
supervisor-proc-exit-listener RUNNING pid 20, uptime 0:41:54
syseepromd EXITED Jul 01 08:01 AM
Example 3-14: PMON - docker exec -it pmon supervisorctl status.
In this output, long-running processes such as ssdhealthd, rsyslogd, and supervisor-proc-exit-listener are active, while several initialization or platform-specific processes have exited. This does not automatically indicate a failure. The expected process set depends on the hardware platform, the SONiC image, and the available platform drivers.
syncd – ASIC Synchronization Service
The syncd container represents the synchronization path between SONiC's hardware-oriented database state and the vendor-specific ASIC implementation. It consumes ASIC_DB updates and passes the corresponding operations through the SAI layer toward the ASIC SDK. Verifying syncd is therefore important when checking whether the boot process has reached the hardware-programming layer.
admin@sonic:~$ systemctl status syncd.service
● syncd.service - syncd service
Loaded: loaded (/lib/systemd/system/syncd.service; enabled; vendor preset:>
Active: active (running) since Wed 2026-07-01 08:00:24 UTC; 31min ago
Process: 4406 ExecStartPre=/usr/local/bin/syncd.sh start (code=exited, stat>
Main PID: 4988 (syncd.sh)
Tasks: 3 (limit: 4289)
Memory: 1.1M
CGroup: /sonic.slice/sonic-core.slice/syncd.service
├─4988 /bin/bash /usr/local/bin/syncd.sh wait
├─4993 /bin/bash /usr/bin/syncd.sh wait
└─5052 tail --pid=4947 -f /dev/null
admin@sonic:~$
Example 3-15: syncd - systemctl status syncd.service.
The output shows that syncd.service is active from the systemd viewpoint. The host-level service is represented by the syncd helper scripts, while the actual syncd daemon runs inside the container. This means that the service status should be combined with the supervisor output before concluding that the ASIC synchronization path is healthy.
admin@sonic:~$ systemctl cat syncd.service
# /lib/systemd/system/syncd.service
[Unit]
Description=syncd service
Requires=database.service
After=database.service
After=swss.service
Requires=updategraph.service
After=updategraph.service
After=interfaces-config.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
[Service]
User=root
Environment=sonic_asic_platform=vs
ExecStartPre=/usr/local/bin/syncd.sh start
ExecStart=/usr/local/bin/syncd.sh wait
ExecStop=/usr/local/bin/syncd.sh stop
Slice=sonic-core.slice
[Install]
WantedBy=sonic.target
admin@sonic:~$
Example 3-16: syncd - systemctl cat syncd.service.
The unit file orders syncd.service after both database.service and swss.service. This matches the SONiC data path described earlier: SWSS writes hardware-oriented state into ASIC_DB, and syncd consumes that state before passing operations to the SAI layer. The additional ordering after updategraph and interface configuration services helps ensure that the service starts with the required platform and interface context.
admin@sonic:~$ docker exec -it syncd supervisorctl status
dependent-startup EXITED Jul 01 08:00 AM
restart-rsyslogd EXITED Jul 01 08:01 AM
rsyslogd RUNNING pid 285, uptime 0:42:43
start EXITED Jul 01 08:00 AM
supervisor-proc-exit-listener RUNNING pid 7, uptime 0:43:37
syncd RUNNING pid 30, uptime 0:43:31
Example 3-17: syncd - docker exec -it syncd supervisorctl status.
The supervisor output confirms that the syncd process is running inside the container. In this type of verification, the systemd service status confirms that the container service is active, while the supervisor output confirms that the actual synchronization daemon inside the container is running.
BGP – FRR Routing Container
The same verification pattern applies to higher-level service containers. BGP, LLDP, teamd, and SNMP are started through systemd service units, but their internal daemons are managed inside their own containers. For these services, systemctl status confirms the host-level service state, systemctl cat shows dependencies and ordering, and supervisorctl status verifies the processes running inside the container.
admin@sonic:~$ systemctl status bgp.service
● bgp.service - BGP container
Loaded: loaded (/lib/systemd/system/bgp.service; enabled; vendor preset: e>
Active: active (running) since Wed 2026-07-01 08:00:16 UTC; 32min ago
Process: 3391 ExecStartPre=/usr/local/bin/bgp.sh start (code=exited, status>
Main PID: 3897 (bgp.sh)
Tasks: 3 (limit: 4289)
Memory: 1.1M
CGroup: /sonic.slice/sonic-bgp.slice/bgp.service
├─3897 /bin/sh /usr/local/bin/bgp.sh wait
├─3898 /bin/bash /usr/bin/bgp.sh wait
└─4089 tail --pid=3828 -f /dev/null
admin@sonic:~$
Example 3-18: BGP - systemctl status bgp.service.
From the systemd perspective, the bgp.service is active at the host level. The helper scripts keep the container service alive from the systemd perspective, but the routing daemons themselves run inside the BGP container. For routing verification, this host-level check should therefore be followed by the supervisor output inside the container.
admin@sonic:~$ systemctl cat bgp.service
# /lib/systemd/system/bgp.service
[Unit]
Description=BGP container
Requires=database.service
After=database.service
Requires=updategraph.service
After=updategraph.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
StartLimitIntervalSec=1200
StartLimitBurst=20
[Service]
User=admin
ExecStartPre=/usr/local/bin/bgp.sh start
ExecStart=/usr/local/bin/bgp.sh wait
ExecStop=/usr/local/bin/bgp.sh stop
Restart=always
RestartSec=30
Slice=sonic-bgp.slice
[Install]
WantedBy=sonic.target
Example 3-19: BGP - systemctl cat bgp.service.
The unit file shows that bgp.service requires the database service and is ordered after it. This is expected because routing state learned by FRR is synchronized into SONiC databases and later consumed by other components. The service is also tied to sonic.target, which places it in the normal SONiC startup sequence.
admin@sonic:~$ docker exec -it bgp supervisorctl status
bfdd RUNNING pid 284, uptime 0:43:17
bgpd RUNNING pid 292, uptime 0:43:17
dependent-startup EXITED Jul 01 08:01 AM
fpmsyncd RUNNING pid 493, uptime 0:43:09
frrcfgd RUNNING pid 378, uptime 0:43:13
ipmcfpmsyncd RUNNING pid 494, uptime 0:43:09
iptrackd RUNNING pid 299, uptime 0:43:17
ospfd RUNNING pid 305, uptime 0:43:17
pimd RUNNING pid 321, uptime 0:43:16
restart-rsyslogd EXITED Jul 01 08:01 AM
rsyslogd RUNNING pid 693, uptime 0:42:48
set_docker_up_status EXITED Jul 01 08:01 AM
staticd RUNNING pid 281, uptime 0:43:17
supervisor-proc-exit-listener RUNNING pid 30, uptime 0:43:58
wait_for_frrcfgd_conn EXITED Jul 01 08:01 AM
wait_for_replay_done EXITED Jul 01 08:00 AM
zebra RUNNING pid 223, uptime 0:43:20
zsocket EXITED Jul 01 08:01 AM
Example 3-20: BGP - docker exec -it bgp supervisorctl status.
The BGP supervisor output confirms that FRR-related processes such as bgpd, zebra, and staticd are running. bgpd handles BGP protocol processing, while zebra maintains routing information inside FRR. fpmsyncd is especially important in SONiC because it synchronizes routing information from FRR toward the SONiC database pipeline.
LLDP – Link Layer Discovery Protocol
The LLDP container is responsible for neighbor discovery and for exchanging link-layer information with directly connected devices. Verifying lldp.service confirms that the host-level container service has started. The supervisor output then confirms that processes such as lldpd, lldpmgrd, and lldp-syncd are running inside the container.
admin@sonic:~$ systemctl status lldp.service
● lldp.service - LLDP container
Loaded: loaded (/lib/systemd/system/lldp.service; enabled; vendor preset: >
Active: active (running) since Wed 2026-07-01 08:01:22 UTC; 31min ago
Process: 7302 ExecStartPre=/usr/bin/lldp.sh start (code=exited, status=0/SU>
Main PID: 9942 (lldp.sh)
Tasks: 2 (limit: 4289)
Memory: 688.0K
CGroup: /system.slice/lldp.service
├─ 9942 /bin/bash /usr/bin/lldp.sh wait
└─10450 tail --pid=9724 -f /dev/null
admin@sonic:~$
Example 3-21: LLDP - systemctl status lldp.service.
The output verifies that lldp.service is active from the systemd viewpoint. This means that the LLDP container service has started successfully, but it does not yet confirm that LLDP neighbor discovery processes are running inside the container. The internal process state is verified separately in the supervisor output.
admin@sonic:~$ systemctl cat lldp.service
# /lib/systemd/system/lldp.service
[Unit]
Description=LLDP container
Requires=database.service
After=database.service
After=swss.service
After=syncd.service
Requires=updategraph.service
After=updategraph.service portinitdone.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
StartLimitIntervalSec=1200
StartLimitBurst=3
[Service]
User=admin
ExecStartPre=/usr/bin/lldp.sh start
ExecStart=/usr/bin/lldp.sh wait
ExecStop=/usr/bin/lldp.sh stop
Restart=always
RestartSec=30
[Install]
WantedBy=sonic.target
Example 3-22: LLDP - systemctl cat lldp.service.
The unit file orders lldp.service after the database, SWSS, syncd, and port-initialization services. This is logical because LLDP depends on initialized interfaces and on the SONiC state pipeline being available. If LLDP starts too early, it may not have the interface context needed to publish accurate neighbor information.
admin@sonic:~$ docker exec -it lldp supervisorctl status
dependent-startup EXITED Jul 01 08:01 AM
lldp-syncd RUNNING pid 120, uptime 0:43:58
lldpd RUNNING pid 63, uptime 0:44:00
lldpmgrd RUNNING pid 145, uptime 0:43:55
restart-rsyslogd STOPPED Not started
rsyslogd RUNNING pid 37, uptime 0:44:04
start EXITED Jul 01 08:01 AM
supervisor-proc-exit-listener RUNNING pid 9, uptime 0:44:05
waitfor_lldp_ready EXITED Jul 01 08:01 AM
Example 3-23: LLDP - docker exec -it lldp supervisorctl status.
The LLDP supervisor output shows that the main LLDP processes are running. lldpd handles the LLDP protocol function, lldpmgrd manages LLDP-related state in SONiC, and lldp-syncd synchronizes LLDP information with the rest of the system. As with other containers, one-shot startup tasks may appear as EXITED, and optional helper processes may remain STOPPED depending on the image and configuration.
teamd – Link Aggregation Service
The teamd container is used for link aggregation and port-channel-related functions. It works with SONiC orchestration components to maintain logical link aggregation state and synchronize port-channel information. Verifying teamd.service is useful when checking whether link aggregation services have started correctly after the lower-level switching services are available.
admin@sonic:~$ systemctl status teamd.service
● teamd.service - TEAMD container
Loaded: loaded (/lib/systemd/system/teamd.service; enabled; vendor preset:>
Active: active (running) since Wed 2026-07-01 08:00:37 UTC; 33min ago
Process: 4407 ExecStartPre=/usr/local/bin/teamd.sh start (code=exited, stat>
Main PID: 5933 (teamd.sh)
Tasks: 3 (limit: 4289)
Memory: 1.0M
CGroup: /system.slice/teamd.service
├─5933 /bin/sh /usr/local/bin/teamd.sh wait
├─5934 /bin/bash /usr/bin/teamd.sh wait
└─6482 tail --pid=5801 -f /dev/null
admin@sonic:~$
Example 3-24: teamd - systemctl status teamd.service.
The output indicates that teamd.service is active from the host systemd viewpoint. This indicates that the container service has started, but it does not confirm the health of the port-channel related daemons inside the container. Those internal processes must be checked with supervisorctl status.
admin@sonic:~$ systemctl cat teamd.service
# /lib/systemd/system/teamd.service
[Unit]
Description=TEAMD container
After=swss.service
Requires=updategraph.service
After=updategraph.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
StartLimitIntervalSec=1200
StartLimitBurst=20
[Service]
User=admin
ExecStartPre=/usr/local/bin/teamd.sh start
ExecStart=/usr/local/bin/teamd.sh wait
ExecStop=/usr/local/bin/teamd.sh stop
Restart=always
RestartSec=30
[Install]
WantedBy=sonic.target
Example 3-25: teamd - systemctl cat teamd.service.
The unit file shows that teamd.service is ordered after swss.service and updategraph.service. This reflects the relationship between port-channel handling and the broader SONiC switching state pipeline. The service also binds to sonic.target, so it is part of the coordinated SONiC startup process.
admin@sonic:~$ docker exec -it teamd supervisorctl status
dependent-startup EXITED Jul 01 08:00 AM
portchannelstatsd FATAL Exited too quickly (process log may have details)
restart-rsyslogd EXITED Jul 01 08:01 AM
rsyslogd RUNNING pid 154, uptime 0:44:42
start EXITED Jul 01 08:00 AM
supervisor-proc-exit-listener RUNNING pid 8, uptime 0:45:29
teammgrd RUNNING pid 89, uptime 0:45:19
teamsyncd RUNNING pid 84, uptime 0:45:22
tlm_teamd RUNNING pid 92, uptime 0:45:17
admin@sonic:~$
Example 3-26: teamd - docker exec -it teamd supervisorctl status.
The teamd supervisor output shows the main teamd-related processes running inside the container. teammgrd participates in SONiC's port-channel management logic, teamsyncd synchronizes team state, and tlm_teamd represents the team daemon process itself. A FATAL state, such as the one shown for portchannelstatsd, should be investigated in context because the expected behavior may depend on the platform, enabled features, and whether port channels are configured in the environment.
SNMP – Simple Network Management Protocol
The SNMP container provides management-plane visibility for external monitoring systems. It exposes SONiC information through SNMP and uses internal helper processes to collect and publish the data that SNMP agents need. Verifying snmp.service confirms that the container is active, while the supervisor output confirms that the internal SNMP processes are running.
admin@sonic:~$ systemctl status snmp.service
● snmp.service - SNMP container
Loaded: loaded (/lib/systemd/system/snmp.service; enabled; vendor preset: >
Active: active (running) since Wed 2026-07-01 08:01:22 UTC; 33min ago
Process: 7308 ExecStartPre=/usr/bin/snmp.sh start (code=exited, status=0/SU>
Main PID: 9946 (snmp.sh)
Tasks: 2 (limit: 4289)
Memory: 708.0K
CGroup: /system.slice/snmp.service
├─ 9946 /bin/bash /usr/bin/snmp.sh wait
└─10459 tail --pid=9674 -f /dev/null
admin@sonic:~$
Example 3-27: SNMP - systemctl status snmp.service.
The output confirms that snmp.service is active from the systemd viewpoint. This means that the SNMP container service has started, but the actual SNMP agent and SONiC-specific helper processes run inside the container. The next verification step is therefore to inspect the supervisor state inside the SNMP container.
admin@sonic:~$ systemctl cat snmp.service
# /lib/systemd/system/snmp.service
[Unit]
Description=SNMP container
Requires=updategraph.service
Requisite=swss.service
After=updategraph.service swss.service syncd.service portinitdone.service
BindsTo=sonic.target
After=sonic.target
Before=ntp-config.service
#Conflicts=snmp.timer
StartLimitIntervalSec=1200
StartLimitBurst=20
[Service]
ExecStartPre=/usr/bin/snmp.sh start
ExecStart=/usr/bin/snmp.sh wait
ExecStop=/usr/bin/snmp.sh stop
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target swss.service
Example 3-28: SNMP - systemctl cat snmp.service.
The unit file shows that snmp.service has a Requisite=swss.service relationship and is ordered after SWSS, syncd, and port initialization. This means SNMP expects the switching state pipeline to be available before the SNMP container is started. This ordering is useful because SNMP exposes management information that depends on data collected and published by other SONiC services.
admin@sonic:~$ docker exec -it snmp supervisorctl status
dependent-startup EXITED Jul 01 08:01 AM
restart-rsyslogd STOPPED Not started
rsyslogd RUNNING pid 30, uptime 0:44:52
snmp-statsd RUNNING pid 50, uptime 0:44:46
snmp-subagent RUNNING pid 47, uptime 0:44:47
snmpconfd RUNNING pid 44, uptime 0:44:49
snmpd RUNNING pid 46, uptime 0:44:48
start EXITED Jul 01 08:01 AM
supervisor-proc-exit-listener RUNNING pid 8, uptime 0:44:56
admin@sonic:~$
Example 3-29: SNMP - docker exec -it snmp supervisorctl status.
The SNMP supervisor output confirms that the SNMP-related processes are running. snmpd provides the SNMP agent function, while snmp-subagent, snmpconfd, and snmp-statsd support SONiC-specific management data and statistics collection. As with the other containers, exited startup helpers are not necessarily errors if they are designed to run only during initialization.
Post-Boot Container Runtime Check
The previous examples verified selected services from the systemd and container-internal viewpoints. A final post-boot check can also be done from the Docker runtime view. This does not replace service-specific verification, but it provides a compact summary of which containers are running and how they are behaving at the moment of inspection.
Running Containers
After individual services have been verified, docker ps provides a quick container-level inventory. The formatted output is easier to read than the default Docker output because it focuses on the container name, image, command, and status. This is useful for confirming that the expected SONiC containers are present and have an uptime that is consistent with the current boot session.
admin@sonic:~$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Command}}"
NAMES IMAGE COMMAND
radv docker-router-advertiser:latest "/usr/bin/docker-ini…"
sflow docker-sflow:latest "/usr/local/bin/supe…"
udld docker-udld:latest "/usr/local/bin/supe…"
lldp docker-lldp:latest "/usr/bin/docker-lld…"
dhcp_relay docker-dhcp-relay:latest "/usr/bin/docker_ini…"
macsec docker-macsec:latest "/usr/local/bin/supe…"
iccpd docker-iccpd:latest "/usr/local/bin/supe…"
stp docker-stp:latest "/usr/local/bin/supe…"
vrrp docker-vrrp:latest "/usr/local/bin/supe…"
l2mcd docker-l2mcd:latest "/usr/local/bin/supe…"
snmp docker-snmp:latest "/usr/local/bin/supe…"
tam docker-tam:latest "/usr/local/bin/supe…"
nat docker-nat:latest "/usr/local/bin/supe…"
telemetry docker-sonic-telemetry:latest "/usr/local/bin/supe…"
teamd docker-teamd:latest "/usr/local/bin/supe…"
pmon docker-platform-monitor:latest "/usr/bin/docker_ini…"
syncd docker-syncd-vs:latest "/usr/local/bin/supe…"
swss docker-orchagent:latest "/usr/bin/docker-ini…"
mgmt-framework docker-sonic-mgmt-framework:latest "/usr/local/bin/supe…"
bgp docker-fpm-frr:latest "/usr/bin/docker_ini…"
eventd docker-eventd:latest "/usr/bin/docker-ini…"
database docker-database:latest "/usr/local/bin/dock…"
admin@sonic:~$
Example 3-30: Docker - docker ps formatted container inventory.
The container list gives a compact view of the running SONiC services. It does not replace service-specific verification, but it is a useful first check after boot. The exact container list depends on the SONiC image, platform, and enabled features. If an expected container is missing from this list, the next step is to check the corresponding systemd unit and its journal output.
Container Resource Usage
docker stats shows live resource usage for running containers. It is useful for observing CPU, memory, I/O, and process count behavior, but it should not be treated as a strict pass/fail test. The values depend on the platform, SONiC image, traffic level, enabled features, and the exact moment when the command is run.
admin@sonic:~$ docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
39f35ad86528 radv 0.22% 22.8MiB / 1.09GiB 2.04% 0B / 0B 6.71MB / 77.8kB 6
383c6f129cf0 sflow 0.26% 41.68MiB / 1.09GiB 3.73% 0B / 0B 5.89MB / 73.7kB 10
41f8aceb0276 udld 0.35% 27.29MiB / 1.09GiB 2.44% 0B / 0B 6.76MB / 73.7kB 9
d00179c7ea91 lldp 1.75% 64.48MiB / 1.09GiB 5.78% 0B / 0B 11.9MB / 119kB 11
234984a05688 dhcp_relay 0.26% 27.41MiB / 1.09GiB 2.46% 0B / 0B 9.2MB / 102kB 8
8154d5347695 macsec 0.63% 79.97MiB / 1.09GiB 7.16% 0B / 0B 13.7MB / 131kB 42
1dd74fba4493 iccpd 0.73% 27.12MiB / 1.09GiB 2.43% 0B / 0B 8.29MB / 86kB 11
2ac43c450769 stp 0.38% 29.6MiB / 1.09GiB 2.65% 0B / 0B 6.53MB / 73.7kB 10
2445d3c5e915 vrrp 6.17% 26.2MiB / 1.08GiB 2.37% 0B / 0B 6.44MB / 73.7kB 11
d7edfc980943 l2mcd 0.36% 25.2MiB / 1.09GiB 2.26% 0B / 0B 6.2MB / 73.7kB 10
5aef3c71eb05 snmp 10.97% 119.6MiB / 1.09GiB 10.71% 0B / 0B 17.2MB / 152kB 20
2da13d8479fc tam 0.48% 29.16MiB / 1.09GiB 2.61% 0B / 0B 9.29MB / 143kB 17
4ccfa496c465 nat 0.34% 24.18MiB / 1.09GiB 2.17% 0B / 0B 6.27MB / 143kB 10
e470557ea1bc telemetry 2.05% 133.8MiB / 1.09GiB 11.99% 0B / 0B 54.6MB / 135kB 16
44a70e26dc76 teamd 0.41% 27.36MiB / 1.09GiB 2.45% 0B / 0B 6.61MB / 168kB 13
0862067c132d pmon 0.39% 52.59MiB / 1.09GiB 4.71% 0B / 0B 19.5MB / 139kB 7
f61ead90462b syncd 3.69% 42.28MiB / 1.09GiB 3.79% 0B / 0B 13.1MB / 115kB 47
70ca44b89efe swss 8.26% 56.46MiB / 1.09GiB 5.06% 0B / 0B 42.8MB / 373kB 57
861772e23d91 mgmt-framework 0.61% 119.7MiB / 1.08GiB 10.82% 0B / 0B 48.2MB / 119kB 14
a9a0074ca931 bgp 3.06% 108.5MiB / 1.09GiB 9.72% 0B / 0B 27.1MB / 287kB 40
8a01d7562616 eventd 0.25% 26.34MiB / 1.09GiB 2.36% 0B / 0B 9.73MB / 106kB 7
e12203dba0e6 database 10.77% 114.5MiB / 1.09GiB 10.26% 0B / 0B 37.9MB / 520kB 36
<Additional refresh cycles omitted for brevity.>
Example 3-31: Docker - docker stats container resource usage.
The example shows that resource usage changes while the command is running. Short CPU spikes can be normal during startup, during Redis activity, or when services process configuration and state updates. A sustained high value, especially combined with service failures or delayed convergence, is more useful as a troubleshooting signal than a single sample.
The examples in this chapter demonstrate that verifying SONiC startup involves three complementary views. systemd confirms that the host-level service units have started, the service unit files explain the dependency and ordering relationships, and supervisorctl verifies that the expected processes are running inside each container. Together, these views provide a structured approach to troubleshooting SONiC startup problems.