How to run swagger-ui with local code changes AND my own swagger.json?

Viewed 17457

The Readme on https://github.com/swagger-api/swagger-ui specifies that Swagger-UI can be run with your own file like this

docker run -p 80:8080 -e SWAGGER_JSON=/foo/swagger.json -v /bar:/foo swaggerapi/swagger-ui

which works I if I translate it to

docker build . -t swagger-ui-local && \
  docker run -p 80:8080 -e SWAGGER_JSON=/foo/my-file.json -v $PWD:/foo swagger-ui-local

This, however, ignores my local changes.

I can run my local changes with

npm run dev

but I can't figure out how to get this dev server to run anything else than the Petstore example.

Can anyone help me combine the two, so I can run swagger-ui with local code changes AND my own swagger.json?

8 Answers

Make sure you are volume mounting the correct local directory.

Locally, I had my swagger config in $PWD/src/app/swagger/swagger.yaml. Running the following worked fine:

docker run -p 80:8080 -e SWAGGER_JSON=/tmp/swagger.yaml -v `pwd`/src/app/swagger:/tmp swaggerapi/swagger-ui

Simply refreshing the Swagger-UI page or clicking the "Explore" button in the header triggered a refresh of the data from my YAML file.

You can also specify BASE_URL excerpt from swagger-installation

docker run -p 80:8080 -e BASE_URL=/swagger -e SWAGGER_JSON=/foo/swagger.json -v /bar:/foo swaggerapi/swagger-ui

I found this topic because I wanted to see a visual representation of my local swagger file, but could not seem to get swagger-ui (running in docker) to display anything other than the petstore.

Ultimately, my issue was with understanding the -e SWAGGER_JSON and -v flags, so I wanted to explain them here.

-v <path1>:<path2>

This option says "Mount the path <path1> from my local file system within the swagger-ui docker container on path <path2>"

-e SWAGGER_JSON=<filepath>

This option says "By default, show the swagger for the file at <filepath> using the docker container's file system." The important part here, is that this filepath should take into account how you set <path2> above

Putting it all together, I ended up with the following:

docker run -p 8085:8080 -e SWAGGER_JSON=/foo/swagger.json -v `pwd`:/foo swaggerapi/swagger-ui

This says in english: "Run my swagger-ui instance on port 8085. Mount my current working directory as '/foo' in the docker container. By default, show the swagger file at '/foo/swagger.json'."

The important thing to note is that I have a file called swagger.json in my current working directory. This command mounts my current working directory as /foo in the docker container. Then, swagger UI can pick up my swagger.json as /foo/swagger.json.

Here's how I ended up solving this, it also allows you to have multiple YML files:

docker run -p 80:8080 \                                                                                                                                 
  -e URLS_PRIMARY_NAME=FIRST \                                                                                                                             
  -e URLS="[ \                                                                                                                                           
    { url: 'docs/first.yml', name: 'FIRST' } \                                                                                                               
    , { url: 'docs/second.yml', name: 'SECOND' } \                                                                                                             
  ]" \                                                                                                                                                   
  -v `pwd`:/usr/share/nginx/html/docs/ \                                                                                                                 
  swaggerapi/swagger-ui   

Docker compose solution:

create .env file and add the following:

URLS_PRIMARY_NAME=FIRST
URLS=[ { url: 'docs/swagger.yaml', name: 'FIRST' } ]

And create a docker-compose file with contents below:

version: "3.3"

services:
 swagger-ui:
  image: swaggerapi/swagger-ui
  container_name: "swagger-ui"
  ports:
    - "80:8080"
  volumes:
   - /local/tmp:/usr/share/nginx/html/docs/
  environment:
    - URLS_PRIMARY_NAME=${URLS_PRIMARY_NAME}
    - URLS=${URLS}

the swagger.yaml is at /local/tmp.

For people facing this issue in mac, its a permission problem. By default after Catalina, docker doesn't have permission to allow its images to read local files in your system. Once its given it worked for me and it took my local swagger json file.

To grant privileges now, go to System preferences > Security & Privacy > Files and Folders, and add Docker for Mac and your shared directory. enter image description here

Another solution if you want to provide multiple URLs and from a specific folder (not default /usr/share/nginx/html/docs/):

docker run -p 80:8080 \
    -e SWAGGER_JSON=/docs/api.yaml \
    -e URLS="[ \
        { url: '/api1.yaml', name: 'API 1' }, \
        { url: '/api2.yaml', name: 'API 2' } \
    ]" \
    -v `pwd`/docs:/docs \
    swaggerapi/swagger-ui

Or for docker compose:

version: '3.8'
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    volumes:
      - ./docs:/docs
    environment:
      SWAGGER_JSON: /docs/api.yaml
      URLS: '[{ url: "/api1.yaml", name: "API 1" }, { url: "/api2.yaml", name: "API 2" }]'

Please note, SWAGGER_JSON requires an absolute path, URLs in URLS require relative paths from the specified volume

Related