I have added a port to the public zone in firewalld but still can't access the port

Using the --permanent flag writes your changes to the persistent configuration, but not the running configuration. Run the same command again without the --permanent flag to have it take effect immediately.

Beginning with RHEL 7.1 and current versions of Fedora, you can also copy the running configuration to the permanent configuration with:

firewall-cmd --runtime-to-permanent

Weirdly, the rule only seemed to be written out to the config file, and not applied immediately. I had to reload the firewall:

firewall-cmd --reload

After this, the rule then showed up:

# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports: 3000/tcp
  masquerade: no
  forward-ports: port=80:proto=tcp:toport=8000:toaddr=
  icmp-blocks:
  rich rules:

The port is now accessible.