Swagger-ui: SWAGGER_JSON=/foo/swagger.json

Created on 7 Jul 2017  Â·  34Comments  Â·  Source: swagger-api/swagger-ui

Doesn't read swagger.json from SWAGGER_JSON path in docker. Copied everything to that folder

Most helpful comment

This works for me:

version: "2"

services:
  swagger_ui:
    environment:
    - API_URL=/swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["./swagger.json:/usr/share/nginx/html/swagger.json"]
    restart: always
    ports:   ["9000:8080"]

All 34 comments

Hi @azamatsulaiman !
I think issue is that doc shows wrong example.

Or you can provide your own swagger.json on your host

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

In case if use
"SWAGGER_JSON=/foo/swagger.json" as parameter it will not be recognized as kwarg. It should be
docker run -p 80:8080 -e SWAGGER_JSON=/foo/swagger.json -v /bar:/foo swaggerapi/swagger-ui

I guess doc should be updated

I tried this work around already but still have same issue @wolendranh

Make sure your path names are correct. I struggled with this issue for an hour before reading the docker-run and seeing what SWAGGER_JSON should have been doing and finding this issue page.

Interesting. Which OS are you on? Just tested both variants (with and without quotes) and they both worked for me.

@webron CentOS 7 - have that issue

@webron Ubuntu 16 -- with quotes was not picking up the env variable correctly

Could you share your docker version? And the exact command you're using? And for completeness, your shell/version ( ie: bash/zsh/fish?).

-e one=two should be identical to -e "one=two" as I believe bash/zsh will remove those.

More importantly, the path your provide should be mounted as a volume, ie: -v /local/path:/foo. foo is arbitrary, and needs to match what you put in SWAGGER_PATH=/foo/...

This command works for me... ( LinuxMint 18)

docker run -p 80:8080 -e SWAGGER_JSON=/foo/petstore.yaml -v /home/josh/:/foo swaggerapi/swagger-ui
# as well as..
docker run -p 80:8080 -e "SWAGGER_JSON=/foo/petstore.yaml" -v /home/josh/:/foo swaggerapi/swagger-ui

# FYI
â–¶ docker version                          
Client:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.4
 Git commit:   78d1802
 Built:        Tue Jan 10 20:38:45 2017
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.4
 Git commit:   78d1802
 Built:        Tue Jan 10 20:38:45 2017
 OS/Arch:      linux/amd64

And also make sure you have the latest docker image...

docker pull swaggerapi/swagger-ui

I definitely have the latest docker image (I actually tried 4 other older tags as well in case there was a docker-run bug introduced at some point).

$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
$ sudo docker version 
Client:
 Version:      1.11.0-rc5
 API version:  1.23
 Go version:   go1.5.3
 Git commit:   6178547
 Built:        Mon Apr 11 21:16:15 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.11.0-rc5
 API version:  1.23
 Go version:   go1.5.3
 Git commit:   6178547
 Built:        Mon Apr 11 21:16:15 2016
 OS/Arch:      linux/amd64

After retrying today I get it work with and without quotes -- but its the identical command I used yesterday when it kept loading http://petstore.swagger.io/v2/swagger.json default page instead. I'm sure what environment setup changed between yesterday and today :/

@MSeal - thanks. I don't mind at all merging your PR, just trying to figure out why it sometimes works and sometimes doesn't. 'magic' is not good enough of a reason ;)

While testing the command, it did take me a few times to get it working, but that's because I had no idea what I was doing with mounting the file system and pointing it to the right place.

Yeah, I think the tricky part is the --volume | -v flag for mounting the directory.
docker will _NOT_ have access to your file system, so you need to mount volumes on to it. We do so with -v ( there is a newer syntax, but its just a more general one, called --mount)

We can enforce a convention, ie remove the need for SWAGGER_JSON env, and just advise users to mount to -v /home/josh/swagger-specs/:/specs where /specs is searched for swagger.yaml | swagger.json file in the docker container. The idea is to force a convention - for simplicity.

+1

I've been searching everywhere for this. In my opinion it would be super convenient to enforce such a convention to enable auto-loading of specs. Would be great if we could suffice with just a docker-compose.yml like so:

version: "2"
services:
  swagger_ui:
    environment:
    - SWAGGER_JSON=./swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["./swagger.json:/usr/share/nginx/html/swagger.json"]
    restart: always
    ports:   ["9000:8080"]

By the way, would be great to also have auto-loading of specs in the editor.

I'm ok with having a default for as a convention, but we should still allow users to have the ability to manually point to a specific file.

yeah I agree @webron

@MidnightP you can have a docker-compose file like that today.... just need to tweak it....

# docker-compose.yaml
version: "2"
services:
  swagger_ui:
    environment:
    - SWAGGER_JSON=/swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["/usr/share/nginx/html/swagger.json:/swagger.json"]
    restart: always
    ports:   ["9000:8080"]

tested that with...

docker-compose --version               
# docker-compose version 1.8.0, build unknown
docker-compose -f ./docker-compose.yaml up

@ponelat Thanks!

Now I receive "Failed to load spec." on initial load... Can the ui read from the root?

version: "2"
services:
  swagger_ui:
    environment:
    - SWAGGER_JSON=/swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["./swagger.json:/swagger.json"]
    restart: always
    ports:   ["9000:8080"]
docker-compose --version
docker-compose version 1.10.0, build 4bd6f1a

@MidnightP yeah it can read from root.
If it can't find the file, it'll show the default petstore.
So it might be the spec.

The above looks fine, you can inspect your mount points if you like...

docker ps # To get the container ID
docker inspect --format '{{.Mounts}}' <docker-container-id>

And also stick your spec into editor.swagger.io to see if there are any validation issues.
Happy hunting :)

This works for me:

version: "2"

services:
  swagger_ui:
    environment:
    - API_URL=/swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["./swagger.json:/usr/share/nginx/html/swagger.json"]
    restart: always
    ports:   ["9000:8080"]

My issue was actually related to docker volumes not functioning properly in windows subsystem linux, it works fine otherwise

Any suggestions on what to change in the docs, or if the PR should be closed? Seems like most of the issues have been more volume based than quote based once investigated.

Perhaps we just add a primer on docker volumes..

Docker volumes

Docker containers are isolated from their hosts in many ways. Including the filesystem.
In order to get your swagger spec inside the docker container, we need to _mount_ or _bind_ it.
docker has the -v or --volume flag to do this. It takes a single argument of the form... -v /laptop-dir/or-file:/docker-dir/or-file:permission-flags. Where the file/dir you want to mount comes first, followed by a colon : and the file/dir that'll be exposed inside the docker container. You can optionally provide permission flags. For example: -v /home/josh/foo.txt:/foo.txt:ro will mount the file in my home directory called foo.txt. The docker container can read this file from /foo.txt, but cannot write to it ( because of the ro flags, read-only).

For our purposes the swagger file can be anywhere on your host, and we typically mount it to /swagger.json on the docker container.

See https://docs.docker.com/engine/admin/volumes/volumes/ for more info. Although it doesn't seem to conver the stuff mentioned above. Maybe there are more apt docs?

We can make it simpler. Ping @webron @shockey

Not sure this is an issue. The specification file via SWAGGER_JSON is mounted inside the container on boot. Therefore you need to provide the volume like this:

docker run -d -p 1337:8080 -e "SWAGGER_JSON=/spec/swagger.json" -v /Projects/cool-api/spec:/spec swaggerapi/swagger-ui

I guess there's room for improvement. In terms of developer experience, it would be better to be able to sync the specification file via a shared volume, instead of only via the container boot. Thoughts?

My suggestion:

# docker-compose.yaml
version: "2"
services:
  swagger_ui:
    environment:
    - SWAGGER_JSON=other-swagger.json
    image:   "swaggerapi/swagger-ui"
    volumes: ["/Projects/cool-api/spec:/spec"]
    restart: always
    ports:   ["1337:8080"]

This way we pass the full spec contents to the container. This allows people to also make use of the $ref. Currently, we only support one root file (if I'm correct). So we only sync 1 file, which causes problems for people using $ref to other spec files, because they are not present in the container.

This way the SWAGGER_JSON is just the identifier for the "root file". We can default this to swagger.json.
So in the example above the /spec/other-swagger.json file would be used to generate the docs.

@guidsen yeah, that's a good idea.
We could easily allow mounting a dir. Ultimately there is a little nginx server in there, which serves up the files. The only issue I can see is, is that they share that server space with the static assets. So you can't have a spec called index.html :grin:

Is there a case where someone would call their spec index.html LOL.

@ponelat If you want I can work on this, this week and create a PR, based on the suggestion I gave. I guess it will really improve the developer experience.

I'd be happy with that. @shockey ?

Sounds good to me!

Volume is taking forever to mount at run time for me so I made a quick Dockerfile that copies the files in there and takes care of the SWAGGER_JSON environment variable, here it is in case someone have a similar issue for whatever reason:

FROM swaggerapi/swagger-ui

EXPOSE 8080

COPY swagger_file.yaml /docs/swagger_file.yaml

ENV SWAGGER_JSON "/docs/swagger_file.yaml"

CMD ["sh", "/usr/share/nginx/docker-run.sh"]

And then to build and run you just need to do:

docker build . -t company/docs
docker run -p 8080:8080 -d company/docs

Not the best way to solve it but at least it works and it's quick.

@faresbessrour How about if i want to mount app/swagger/swagger_file.yaml to /docs/swagger_file.yaml?. Because i would like to sync file from host to docker container while i editing swagger file.
I'm using docker-compose

Absolutely @minhloc2011 instead of using a Dockerfile you can use a docker-compose config like this one:

version: '3'
services:
  swagger:
    image: swaggerapi/swagger-ui
    ports:
      - 8080:8080
    volumes:
      - ./app/swagger/swagger_file.yaml:/docs/swagger_file.yaml
    environment:
      - SWAGGER_JSON="/docs/swagger_file.yaml"

What you do here is you mount your host file located in ./app/swagger/swagger_file.yaml to the /docs/swagger_file.yaml file in the container and then give it as an environment virable in SWAGGER_JSON

Mind you I didn't test this file but it should look very similar to what I have, please tag me if there is any correction to make on it!

Hope this helps.

@faresbessrour thank for reply, i got it!

The root cause of this problem is the permission issue of nginx. This soft link file does not have access to the final directory. Need to change the mounted host directory to readable.
eg:
docker run --name=ui -p 1080:8080 --privileged -e SWAGGER_JSON=/foo/swagger.json -v /root:/foo -d swaggerapi/swagger-ui

chmod 755 -R /root

I have a swagger.json on my desktop, so running this command worked:

docker run -p 9000:8080 -e SWAGGER_JSON=/mnt/swagger.json -v ~/Desktop:/mnt swaggerapi/swagger-ui

localhost:9000 is loading correct file.

After an embarrassingly long time, I realized my browser was caching. Ctrl-F5 and I was seeing my swagger.json instead of the default.

Was this page helpful?
0 / 5 - 0 ratings