Can't connect to service in local virtual host

I’m new to docker and following this tutorial https://docs.docker.com/get-started/part4/#configure-a-docker-machine-shell-to-the-swarm-manager but stuck at this step
I can’t connect to a website which running in service in virtual machine :cold_sweat::

-> % curl  192.168.99.100
curl: (7) Failed to connect to 192.168.99.100 port 80: Connection refused

Some investigations:

-> % docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   *        virtualbox   Running   tcp://192.168.99.100:2376           v18.09.0
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.0
-> % docker-machine ssh myvm2 "docker logs 76fe7af9a731"
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

docker-compose.yml

version: "3"
services:
  web:
    image: thaihoa311/learn-docker:part2
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

Dockerfile

FROM python:2.7-slim

WORKDIR /app

COPY . /app

RUN pip install --trusted-host pypi.python.org -r requirements.txt

EXPOSE 80

ENV NAME world

CMD ["python", "app.py"]

I’m new to this too but,
Looks like you may find it at port 2376.

Have you tried connecting to http://$(docker-machine ip):4000/ instead of at :80? I’m noticing that you’ve got ports exposing 4000:80 in your docker-compose.yml, so it should in theory be accessible over port 4000.

That said, I’m having the exact same issue as you, and I can’t connect to $(docker-machine ip) or localhost over ports 80 or 4000, yet everything sure looks fine when I run

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                      PORTS
76o9xuv872a1        getstartedlab_web   replicated          5/5                 daaang/get-started:part2   *:4000->80/tcp
$ docker network ls
NETWORK ID          NAME                   DRIVER              SCOPE
c9ee870b9fb4        bridge                 bridge              local
ad65b92160c1        docker_gwbridge        bridge              local
x2bmjimceve7        getstartedlab_webnet   overlay             swarm
ed471b8dea46        host                   host                local
qtenzplm9d1v        ingress                overlay             swarm
2f44eb792dec        none                   null                local

When I inspect getstartedlab_webnet, I get a dump that looks healthy enough, although I guess I have no way of knowing that. At least, it ends with

        "Peers": [
            {
                "Name": "7551e0c18be2",
                "IP": "192.168.99.100"
            }
        ]

which is the right ip for the docker vm. I’m out of ideas for the moment.