Display API specifications with Laravel + SwaggerUI + Docker

Aug 27, 2020 PHP Laravel Docker

#Introduction Launch the Swagger UI container with Docker and display the API specifications from the API created with Laravel.

Thing you want to do

What this article does not touch

Directory structure

.
├── docker-file
│ └── web
│ ├── Dockerfile
│ └── php.ini
├── swagger-docs
│ └── swagger.json
├── volumes
│ └── swagger-api
└── docker-compose.yml

Contents of each file

docker-compose.yml

Since the focus is on swagger-ui this time, the description of db items is omitted.

version: '3'

services:

  web:
    container_name: web
    build: ./docker-file/web/
    ports:
      -8080:80
    volumes:
      -./volumes/swagger-api:/var/www/html/swagger-api
      
  db:
    container_name: mysql
    ....

  swagger:
    container_name: swagger-ui
    image: swaggerapi/swagger-ui
    volumes:
      -./swagger-docs/swagger.json:/usr/share/nginx/html/swagger.json
    environment:
      API_URL: swagger.json
    ports:
      -"8081:8080"

docker-file/web/Dockerfile

FROM php:7.4-apache

COPY ./php.ini /usr/local/etc/php/

RUN apt-get update \
  && apt-get install --no-install-recommends -y git curl wget sudo libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libmcrypt-dev libxml2-dev libpq-dev libzip-dev libpq5 postgresql-client default-mysql-client libicu-dev libonig-dev \
  && mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled \
  && docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ \
  && docker-php-ext-install -j$(nproc) zip gd xml pdo pdo_mysql mysqli soap intl \
  && rm -r /var/lib/apt/lists/*

RUN /bin/sh -c a2enmod rewrite

docker-file/web/php.ini

[Core]
display_errors = On
error_reporting = E_ALL
error_log = /var/log/apache2/error.log
log_errors = On

[Date]
date.timezone ='Asia/Tokyo'

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = auto
mbstring.http_input = auto
mbstring.http_output = auto
mbsting.encoding_translation = Off
mbstring.detect_order = auto

swagger-docs/swagger.json

Prepare an empty file.

execute

Start with docker-compose.

$ docker-compose up -d
Creating network "swagger-ui-docker_default" with the default driver
Creating swagger-ui ... done
Creating mysql ... done
Creating web ... done

#Swagger

Install

Install the required libraries with composer. The latest version is 3.x series, but since it seems to be quite different from the 2.x series that I used before, this time I will install the latest version of 2.x series.

$ composer require zircote/swagger-php:2.0.16

Set up php file for Swagger

Create a php file in the directory where you want to generate the documentation. This time, place it directly under the Controllers directory.

<?php

/**
 * @SWG\Swagger(
 * @SWG\Info(
 * version="1.0",
 * title="Laravel API Specification",
 *),
 *)
 */

Describe comments for Swagger in Controller

This time, I created a ProductController with Get/Post/Put/Delete as an example. The contents of the method are omitted.

<?php

....

class ProductController extends Controller
{

    /**
     * @SWG\Get(
     * path="/api/product/{product_id}",
     * summary="Get product information",
     * description="Get product information.",
     * produces={"application/json"},
     * tags={"Product"},
     * @SWG\Parameter(
     * name="product_id",
     * description="Product ID",
     * in="path",
     * required=true,
     * type="integer"
     *),
     * @SWG\Response(
     * response=200,
     * description="Success",
     * ),
     * @SWG\Response(
     * response=400,
     * description="Bad Request error",
     *),
     * @SWG\Response(
     * response=401,
     * description="Unauthorized error"
     * ),
     *)
     */
    public function show($product_id)
    {
        ....
    }

    /**
     * @SWG\Post(
     * path="/api/product",
     * summary="Register product information",
     * description = "Register product information.",
     * produces={"application/json"},
     * tags={"Product"},
     * @SWG\Parameter(
     * in="body",
     * name="Product",
     * description="List of product object",
     * @SWG\Schema(
     * type="object",
     * @SWG\Property(property="code", type="string", description="Product code"),
     * @SWG\Property(property="name", type="string", description="product name"),
     * @SWG\Property(property="price", type="integer", description="sales price"),
     *)
     * ),
     * @SWG\Response(
     * response=200,
     * description="Success",
     * ),
     * @SWG\Response(
     * response=400,
     * description="Bad Request error",
     *),
     * @SWG\Response(
     * response=401,
     * description="Unauthorized error"
     *),
     *)
     */
    public function store(Request $request)
    {
        ....
    }

    /**
     * @SWG\Put(
     * path="/api/product",
     * summary="Update product information",
     * description="Update product information.",
     * produces={"application/json"},*     tags={"Product"},
     *     @SWG\Parameter(
     *         in="body",
     *         name="Product",
     *         description="List of product object",
     *         @SWG\Schema(
     *             type="object",
     *             @SWG\Property(property="product_id", type="integer", description="商品ID"),
     *             @SWG\Property(property="code", type="string", description="商品コード"),
     *             @SWG\Property(property="name", type="string", description="商品名"),
     *             @SWG\Property(property="price", type="integer", description="販売価格"),
     *         )
     *     ),
     *     @SWG\Response(
     *         response=200,
     *         description="Success",
     *     ),
     *     @SWG\Response(
     *         response=400,
     *         description="Bad Request error",
     *     ),
     *     @SWG\Response(
     *         response=401,
     *         description="Unauthorized error"
     *     ),
     * )
     */
    public function update(Request $request)
    {
        ....
    }

    /**
     * @SWG\Delete(
     *     path="/api/product",
     *     summary="商品情報削除",
     *     description="商品情報を削除します。",
     *     produces={"application/json"},
     *     tags={"Product"},
     *     @SWG\Parameter(
     *         in="body",
     *         name="Product",
     *         description="List of product object",
     *         @SWG\Schema(
     *             type="object",
     *             @SWG\Property(property="product_id", type="integer", description="商品ID"),
     *         ),
     *     ),
     *     @SWG\Response(
     *         response=200,
     *         description="Success",
     *     ),
     *     @SWG\Response(
     *         response=400,
     *         description="Bad Request error",
     *     ),
     *     @SWG\Response(
     *         response=401,
     *         description="Unauthorized error"
     *     ),
     * )
     */
    public function destroy(Request $request)
    {
        ....
    }
}

swagger.json生成

以下コマンドで、記載したコメントからswagger.jsonを生成します。

$ vendor/bin/swagger app/Http/Controllers/ -o ../../swagger-docs/

ブラウザで確認

docker-compose.ymlで先ほど出力したswagger-docs/swagger.jsonを参照するようにしているので、以下URLにアクセスするとAPI仕様書が確認できるようになっています。

http://localhost:8081/

localhost_8081_.png